Skip to main content

Import XML data into AEM

Hi everyone, in this post, we will see how can we import XML data into AEM.

 Sometimes, we have an XML file in the system from which we need to import or sometimes we have XML data exposed via a URL. We will see both methods.

Design

We will be creating the following to make this work - 

  1. OSGi configuration - This will capture the location of the XML file and the URL which is exposing the XML data. It will also let us define the location in crx/de, where we want to import the data.
  2. Sling Scheduler - This scheduler will run periodically and read both file and URL to fetch the data. You can have more control over this by defining an AEM component etc or a separate console.
  3. XML Reader Service - This OSGi service will be invoked by the scheduler and will read/parse the data from file/URL using JAXB (Java Architecture for XML binding) library.
  4. XML Writer Service - This OSGi service will make use of JCR Node APIs to write parsed XML data into crx/de at the specified location.

XML Data Source

You can find the XML file which is used as a datasource is present here.
The URL which is being used as a datasource is here.

Both of these datasources have actually the same data - one in the form of file and other as a URL.

Battle with code

So, without further ado, let's see the code in action.

  • Create an OSGi service
package org.redquark.aem.xmlreader.core.configurations;

import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.AttributeType;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;

/**
 * @author Anirudh Sharma
 *
 */
@ObjectClassDefinition(
  name = "Red Quark XML Reader", 
  description = "This configuration lets us read XML file from the system or XML response from a URLl̥")
public @interface XMLReaderConfiguration {
 
     @AttributeDefinition(
       name = "Scheduler name", 
       description = "Name of the scheduler", 
       type = AttributeType.STRING)
     public String name() default "XML Reader Scheduler";

     @AttributeDefinition(
       name = "Enabled", 
       description = "Flag to enable/disable a scheduler", 
       type = AttributeType.BOOLEAN)
     public boolean enabled() default true;

     @AttributeDefinition(
       name = "Cron expression", 
       description = "Cron expression used by the scheduler", 
       type = AttributeType.STRING)
     public String cronExpression() default "0 * * * * ?";

     @AttributeDefinition(
      name = "XML file path", 
      description = "Path of the XML file on the system", 
      type = AttributeType.STRING)
     public String xmlFilePath();
 
            @AttributeDefinition(
      name = "XML response URL", 
      description = "URL from where XML response is to be read", 
      type = AttributeType.STRING)
     public String xmlResponseURL();
 
     @AttributeDefinition(
      name = "JCR path", 
      description = "Path in the JCR to store data", 
      type = AttributeType.STRING)
     public String jcrPath();
}

As you see, we have attributes for reading the XML file's path and the URL where the XML is stored. We also have the path where we need to import the XML data in crx/de. Apart from these parameters, we have a field to enter cron expression which will be used to control how frequently will this scheduler run.

  • Creating a sling scheduler

package org.redquark.aem.xmlreader.core.schedulers;

import org.apache.sling.commons.scheduler.ScheduleOptions;
import org.apache.sling.commons.scheduler.Scheduler;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Modified;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.metatype.annotations.Designate;
import org.redquark.aem.xmlreader.core.configurations.XMLReaderConfiguration;
import org.redquark.aem.xmlreader.core.models.ProductList;
import org.redquark.aem.xmlreader.core.services.XMLReaderService;
import org.redquark.aem.xmlreader.core.services.XMLWriterService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author Anirudh Sharma
 *
 */
@Component(immediate = true, service = Runnable.class)
@Designate(ocd = XMLReaderConfiguration.class)
public class XMLReaderScheduler implements Runnable {

     // Logger
     private final Logger log = LoggerFactory.getLogger(this.getClass());

     // Id of the scheduler based on its name
     private int schedulerId;

     // Scheduler instance injected
     @Reference
     private Scheduler scheduler;

     // XMLReaderService is injected
     @Reference
     private XMLReaderService xmlReaderService;

     // XMLWriterService is injected
     @Reference
     private XMLWriterService xmlWriterService;

     // Path of the XML file
     private String filePath;

     // URL of the XML response
     private String url;

     // Flag to check if the scheduler is enabled
     private boolean isEnabled;

     // Path where data is to be stored in JCR
     private String jcrPath;

     /**
      * Activate method to initialize stuff
      * 
      * @param xmlReaderConfiguration
      */
     @Activate
     protected void activate(XMLReaderConfiguration xmlReaderConfiguration) {
      schedulerId = xmlReaderConfiguration.name().hashCode();
      filePath = xmlReaderConfiguration.xmlFilePath();
      url = xmlReaderConfiguration.xmlResponseURL();
      isEnabled = xmlReaderConfiguration.enabled();
      jcrPath = xmlReaderConfiguration.jcrPath();
     }

     /**
      * Modifies the scheduler id on modification
      * 
      * @param xmlReaderConfiguration
      */
     @Modified
     protected void modified(XMLReaderConfiguration xmlReaderConfiguration) {
      // Removing scheduler
      removeScheduler();
      // Updating the scheduler id
      schedulerId = xmlReaderConfiguration.name().hashCode();
      // Again adding the scheduler
      addScheduler(xmlReaderConfiguration);
     }

     /**
      * This method deactivates the scheduler and removes it
      * 
      * @param xmlReaderConfiguration
      */
     @Deactivate
     protected void deactivate(XMLReaderConfiguration xmlReaderConfiguration) {
      // Removing the scheduler
      removeScheduler();
     }

     /**
       * This method removes the scheduler
       */
     private void removeScheduler() {
      log.info("Removing scheduler: {}", schedulerId);
      // Unscheduling/removing the scheduler
      scheduler.unschedule(String.valueOf(schedulerId));
     }

     /**
       * This method adds the scheduler
       * 
       * @param schedulerConfiguration
       */
      private void addScheduler(XMLReaderConfiguration xmlReaderConfiguration) {
       // Check if the scheduler is enabled
       if (isEnabled) {
       // Scheduler option takes the cron expression as a parameter and run accordingly
       ScheduleOptions scheduleOptions = scheduler.EXPR(xmlReaderConfiguration.cronExpression());

       // Adding some parameters
       scheduleOptions.name(xmlReaderConfiguration.name());
       scheduleOptions.canRunConcurrently(false);

       // Scheduling the job
       scheduler.schedule(this, scheduleOptions);
       log.info("Scheduler added");
      } else {
       log.info("Scheduler is disabled");
      }
     }

     /**
      * Overridden run method to execute Job
      */
     @Override
     public void run() {
      if (isEnabled) {
       ProductList productList = null;
       // Reads XML data from a file in the system
       if (filePath != null && !filePath.isEmpty()) {
        productList = xmlReaderService.readXMLFromFile(filePath);
        xmlWriterService.writeXMLToJCR(productList, jcrPath, "file");
       }

       // Reads XML data from a response
       if (url != null && !url.isEmpty()) {
        productList = xmlReaderService.readXMLFromURL(url);
        xmlWriterService.writeXMLToJCR(productList, jcrPath, "url");
       }
      }
     }
}
As you can see, we have a mechanism to run scheduler via activate(), modified() and deactivate() methods. You can see their details and concepts in this article.
Inside the run() method which will run based on the value of the cron expression, we are calling XMLReaderService and XMLWriterService to read and write the XML data respectively.
These two services are defined in the following sections.

  • XMLReaderService

This service will read the data from both the sources i.e. from the file and the URL. Below is the code for the same - 
package org.redquark.aem.xmlreader.core.services.impl;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

import org.osgi.service.component.annotations.Component;
import org.redquark.aem.xmlreader.core.models.ProductList;
import org.redquark.aem.xmlreader.core.services.XMLReaderService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author Anirudh Sharma
 */
@Component(immediate = true, service = XMLReaderService.class)
public class XMLReaderServiceImpl implements XMLReaderService {

 // Logger
 private final Logger log = LoggerFactory.getLogger(this.getClass());
 
 // JAXB instance
 private JAXBContext jaxbContext;
 
 // JAXB Unmarshaller
 private Unmarshaller unmarshaller;
 

 @Override
 public ProductList readXMLFromFile(String filePath) {
  
  ProductList productList = null;

  try {

   // Creating a file object from the XML file
   File file = new File(filePath);

   jaxbContext = JAXBContext.newInstance(ProductList.class);

   unmarshaller = jaxbContext.createUnmarshaller();

   productList = (ProductList) unmarshaller.unmarshal(file);

  } catch (Exception e) {
   log.error(e.getMessage(), e);
  }
  
  return productList;
 }

 @Override
 public ProductList readXMLFromURL(String responseURL) {

  URLConnection urlConnection = null;
  InputStreamReader inputStreamReader = null;
  StringBuilder builder = new StringBuilder();
  ProductList productList = null;

  try {
   URL url = new URL(responseURL);
   urlConnection = url.openConnection();

   if (urlConnection != null) {
    urlConnection.setReadTimeout(30 * 1000);
   }

   if (urlConnection != null && urlConnection.getInputStream() != null) {

    inputStreamReader = new InputStreamReader(urlConnection.getInputStream(), Charset.defaultCharset());
    BufferedReader bufferedReader = new BufferedReader(inputStreamReader);

    if (bufferedReader != null) {
     int eof;
     while ((eof = bufferedReader.read()) != -1) {
      builder.append((char) eof);
     }
     bufferedReader.close();
    }
   }
   inputStreamReader.close();
  } catch (Exception e) {
   log.error(e.getMessage(), e);
  }
  
  String xmlResponse = builder.toString();
  xmlResponse = xmlResponse.substring(xmlResponse.indexOf("\n") + 1);
  
  try {
   
   jaxbContext = JAXBContext.newInstance(ProductList.class);
   
   unmarshaller = jaxbContext.createUnmarshaller();
   
   productList = (ProductList) unmarshaller.unmarshal(new StringReader(xmlResponse));
   
  } catch (JAXBException e) {
   log.info(e.getMessage(), e);
  }
  
  return productList;
 }
}

Here we have two methods, one for reading data from the file where we using java.io API to read file and JAXB API to convert XML data to our Products model class which is defined below.

In the other method, we are using URLConnection API to read the data from the URL defined above. After reading the data, we are transforming it again into our model classes.

Once the XML data is converted into the model object then it is returned back to the sling scheduler where it is consumed by our XMLWriter service to write data into JCR.

  • XMLWriterService

This OSGi gets the transformed object and writes the data present in it to our JCR.
package org.redquark.aem.xmlreader.core.services.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;

import org.apache.sling.api.resource.LoginException;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.redquark.aem.xmlreader.core.models.Product;
import org.redquark.aem.xmlreader.core.models.ProductList;
import org.redquark.aem.xmlreader.core.services.XMLWriterService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author Anirudh Sharma
 */
@Component(immediate = true, service = XMLWriterService.class)
public class XMLWriterServiceImpl implements XMLWriterService {

 // Logger
 private final Logger log = LoggerFactory.getLogger(this.getClass());

 // Injecting ResourceResolverFactory
 @Reference
 private ResourceResolverFactory resourceResolverFactory;

 // JCR session
 private Session session;

 /**
  * This method writes XML data to the JCR repository
  */
 @Override
 public void writeXMLToJCR(ProductList productList, String jcrPath, String from) {

  log.info("Writing XML data to nodes from: {}", from);

  try {

   // Getting the session
   session = getSession();

   // Getting root node of the CRX repository
   Node root = session.getRootNode();

   // Getting the reference of the node under which we need to create our nodes
   Node xmlNode = root.getNode(jcrPath);

   // Parent node of all the children nodes which are represented by individual
   // XML items
   Node xmlDataNode = null;

   // Checks if the source is from XML file and the node is already present
   if (from.equalsIgnoreCase("file") && !xmlNode.hasNode("xml_file_products")) {
    xmlDataNode = xmlNode.addNode("xml_file_products", "sling:OrderedFolder");
   }

   // Checks if the source is from URL and the node is already present
   if (from.equalsIgnoreCase("url") && !xmlNode.hasNode("xml_url_products")) {
    xmlDataNode = xmlNode.addNode("xml_url_products", "sling:OrderedFolder");
   }

   // Setting the title of the node
   if (xmlDataNode != null) {
    xmlDataNode.setProperty("jcr:title", "Products");
   } else {
    return;
   }

   // Getting the products from ProductList
   List<Product> products = productList.getProduct();

   // Iterate for each item present in the XML file
   for (Product product : products) {
    
    Node currentNode = null;

    if (!xmlDataNode.hasNode("product_" + product.getProductId())) {
     currentNode = xmlDataNode.addNode("product_" + product.getProductId(), "nt:unstructured");
    } else {
     currentNode = xmlDataNode.getNode("product_" + product.getProductId());
    }

    // Setting properties of the node
    currentNode.setProperty("Product_ID", product.getProductId());
    currentNode.setProperty("SKU", product.getSku());
    currentNode.setProperty("Name", product.getName());
    currentNode.setProperty("Product_URL", product.getProductUrl());
    currentNode.setProperty("Price", product.getPrice());
    currentNode.setProperty("Retail_Price", product.getRetailPrice());
    currentNode.setProperty("Thumbnail_URL", product.getThumbnailUrl());
    currentNode.setProperty("Search_Keywords", product.getSearchKeywords());
    currentNode.setProperty("Description", product.getDescription());
    currentNode.setProperty("Category", product.getCategory());
    currentNode.setProperty("Category_ID", product.getCategoryId());
    currentNode.setProperty("Brand", product.getBrand());
    currentNode.setProperty("Child_SKU", product.getChildSku());
    currentNode.setProperty("Child_Price", product.getChildPrice());
    currentNode.setProperty("Color", product.getColor());
    currentNode.setProperty("Color_Family", product.getColorFamily());
    currentNode.setProperty("Color_Swatches", product.getColorSwatches());
    currentNode.setProperty("Size", product.getSize());
    currentNode.setProperty("Shoe_Size", product.getShoeSize());
    currentNode.setProperty("Pants_Size", product.getPantsSize());
    currentNode.setProperty("Occassion", product.getOccassion());
    currentNode.setProperty("Season", product.getSeason());
    currentNode.setProperty("Badges", product.getBadges());
    currentNode.setProperty("Rating_Avg", product.getRatingAvg());
    currentNode.setProperty("Rating_Count", product.getRatingCount());
    currentNode.setProperty("Inventory_Count", product.getInventoryCount());
    currentNode.setProperty("Date_Created", product.getDateCreated());
   }

   // Saving the changes to JCR
   session.save();

  } catch (RepositoryException e) {
   log.error(e.getMessage(), e);
  }
 }

 private Session getSession() {
  try {
   // Map for service user details
   Map<String, Object> xmlReaderMap = new HashMap<>();
   xmlReaderMap.put(ResourceResolverFactory.SUBSERVICE, "xmlReaderSubservice");

   // Getting ResourceResovler
   ResourceResolver resourceResolver = resourceResolverFactory.getServiceResourceResolver(xmlReaderMap);

   // Getting the session by adapting the resourceResolver
   session = resourceResolver.adaptTo(Session.class);

  } catch (LoginException e) {
   log.error(e.getMessage(), e);
  }
  return session;
 }
}

  • Model classes

Below are our model classes (these classes are based on my datasource - you need to create your model classes as per your datasource). These model classes use @XmlRootElement(name = "Products") and @XmlRootElement(name = "Product") to define the XML tag they are reading.
package org.redquark.aem.xmlreader.core.models;

import java.io.Serializable;
import java.util.List;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

/**
 * @author Anirudh Sharma
 *
 */
@XmlRootElement(name = "Products")
@XmlAccessorType(XmlAccessType.FIELD)
public class ProductList implements Serializable {

 // Generated serialVersionUID
 private static final long serialVersionUID = -7423990858185520203L;

 // Instance of one product
 @XmlElement(name = "Product")
 private List<Product> product;

 public ProductList() {
  super();
 }

 /**
  * @param product
  */
 public ProductList(List<Product> product) {
  super();
  this.product = product;
 }

 /**
  * @return the product
  */
 public List<Product> getProduct() {
  return product;
 }

 /**
  * @param product
  *            the product to set
  */
 public void setProduct(List<Product> product) {
  this.product = product;
 }

 /**
  * Overridden toString() method
  */
 @Override
 public String toString() {
  return "ProductList [product=" + product + "]";
 }
}

package org.redquark.aem.xmlreader.core.models;

import java.io.Serializable;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

/**
 * @author Anirudh Sharma
 *
 */
@XmlRootElement(name = "Product")
@XmlAccessorType(XmlAccessType.FIELD)
public class Product implements Serializable {

 /**
  * Generated serialVersionUID
  */
 private static final long serialVersionUID = -2525852165658067914L;

 @XmlElement(name = "Product_ID")
 private String productId;

 @XmlElement(name = "SKU")
 private String sku;

 @XmlElement(name = "Name")
 private String name;

 @XmlElement(name = "Product_URL")
 private String productUrl;

 @XmlElement(name = "Price")
 private double price;

 @XmlElement(name = "Retail_Price")
 private double retailPrice;

 @XmlElement(name = "Thumbnail_URL")
 private String thumbnailUrl;

 @XmlElement(name = "Search_Keywords")
 private String searchKeywords;

 @XmlElement(name = "Description")
 private String description;

 @XmlElement(name = "Category")
 private String category;

 @XmlElement(name = "Category_ID")
 private String categoryId;

 @XmlElement(name = "Brand")
 private String brand;

 @XmlElement(name = "Child_SKU")
 private String childSku;

 @XmlElement(name = "Child_Price")
 private String childPrice;

 @XmlElement(name = "Color")
 private String color;

 @XmlElement(name = "Color_Family")
 private String colorFamily;

 @XmlElement(name = "Color_Swatches")
 private String colorSwatches;

 @XmlElement(name = "Size")
 private String size;

 @XmlElement(name = "Shoe_Size")
 private String shoeSize;

 @XmlElement(name = "Pants_Size")
 private String pantsSize;

 @XmlElement(name = "Occassion")
 private String occassion;

 @XmlElement(name = "Season")
 private String season;

 @XmlElement(name = "Badges")
 private String badges;

 @XmlElement(name = "Rating_Avg")
 private double ratingAvg;

 @XmlElement(name = "Rating_Count")
 private int ratingCount;

 @XmlElement(name = "Inventory_Count")
 private int inventoryCount;

 @XmlElement(name = "Date_Created")
 private String dateCreated;

 /**
  * @return the productId
  */
 public String getProductId() {
  return productId;
 }

 /**
  * @param productId
  *            the productId to set
  */
 public void setProductId(String productId) {
  this.productId = productId;
 }

 /**
  * @return the sku
  */
 public String getSku() {
  return sku;
 }

 /**
  * @param sku
  *            the sku to set
  */
 public void setSku(String sku) {
  this.sku = sku;
 }

 /**
  * @return the name
  */
 public String getName() {
  return name;
 }

 /**
  * @param name
  *            the name to set
  */
 public void setName(String name) {
  this.name = name;
 }

 /**
  * @return the productUrl
  */
 public String getProductUrl() {
  return productUrl;
 }

 /**
  * @param productUrl
  *            the productUrl to set
  */
 public void setProductUrl(String productUrl) {
  this.productUrl = productUrl;
 }

 /**
  * @return the price
  */
 public double getPrice() {
  return price;
 }

 /**
  * @param price
  *            the price to set
  */
 public void setPrice(double price) {
  this.price = price;
 }

 /**
  * @return the retailPrice
  */
 public double getRetailPrice() {
  return retailPrice;
 }

 /**
  * @param retailPrice
  *            the retailPrice to set
  */
 public void setRetailPrice(double retailPrice) {
  this.retailPrice = retailPrice;
 }

 /**
  * @return the thumbnailUrl
  */
 public String getThumbnailUrl() {
  return thumbnailUrl;
 }

 /**
  * @param thumbnailUrl
  *            the thumbnailUrl to set
  */
 public void setThumbnailUrl(String thumbnailUrl) {
  this.thumbnailUrl = thumbnailUrl;
 }

 /**
  * @return the searchKeywords
  */
 public String getSearchKeywords() {
  return searchKeywords;
 }

 /**
  * @param searchKeywords
  *            the searchKeywords to set
  */
 public void setSearchKeywords(String searchKeywords) {
  this.searchKeywords = searchKeywords;
 }

 /**
  * @return the description
  */
 public String getDescription() {
  return description;
 }

 /**
  * @param description
  *            the description to set
  */
 public void setDescription(String description) {
  this.description = description;
 }

 /**
  * @return the category
  */
 public String getCategory() {
  return category;
 }

 /**
  * @param category
  *            the category to set
  */
 public void setCategory(String category) {
  this.category = category;
 }

 /**
  * @return the categoryId
  */
 public String getCategoryId() {
  return categoryId;
 }

 /**
  * @param categoryId
  *            the categoryId to set
  */
 public void setCategoryId(String categoryId) {
  this.categoryId = categoryId;
 }

 /**
  * @return the brand
  */
 public String getBrand() {
  return brand;
 }

 /**
  * @param brand
  *            the brand to set
  */
 public void setBrand(String brand) {
  this.brand = brand;
 }

 /**
  * @return the childSku
  */
 public String getChildSku() {
  return childSku;
 }

 /**
  * @param childSku
  *            the childSku to set
  */
 public void setChildSku(String childSku) {
  this.childSku = childSku;
 }

 /**
  * @return the childPrice
  */
 public String getChildPrice() {
  return childPrice;
 }

 /**
  * @param childPrice
  *            the childPrice to set
  */
 public void setChildPrice(String childPrice) {
  this.childPrice = childPrice;
 }

 /**
  * @return the color
  */
 public String getColor() {
  return color;
 }

 /**
  * @param color
  *            the color to set
  */
 public void setColor(String color) {
  this.color = color;
 }

 /**
  * @return the colorFamily
  */
 public String getColorFamily() {
  return colorFamily;
 }

 /**
  * @param colorFamily
  *            the colorFamily to set
  */
 public void setColorFamily(String colorFamily) {
  this.colorFamily = colorFamily;
 }

 /**
  * @return the colorSwatches
  */
 public String getColorSwatches() {
  return colorSwatches;
 }

 /**
  * @param colorSwatches
  *            the colorSwatches to set
  */
 public void setColorSwatches(String colorSwatches) {
  this.colorSwatches = colorSwatches;
 }

 /**
  * @return the size
  */
 public String getSize() {
  return size;
 }

 /**
  * @param size
  *            the size to set
  */
 public void setSize(String size) {
  this.size = size;
 }

 /**
  * @return the shoeSize
  */
 public String getShoeSize() {
  return shoeSize;
 }

 /**
  * @param shoeSize
  *            the shoeSize to set
  */
 public void setShoeSize(String shoeSize) {
  this.shoeSize = shoeSize;
 }

 /**
  * @return the pantsSize
  */
 public String getPantsSize() {
  return pantsSize;
 }

 /**
  * @param pantsSize
  *            the pantsSize to set
  */
 public void setPantsSize(String pantsSize) {
  this.pantsSize = pantsSize;
 }

 /**
  * @return the occassion
  */
 public String getOccassion() {
  return occassion;
 }

 /**
  * @param occassion
  *            the occassion to set
  */
 public void setOccassion(String occassion) {
  this.occassion = occassion;
 }

 /**
  * @return the season
  */
 public String getSeason() {
  return season;
 }

 /**
  * @param season
  *            the season to set
  */
 public void setSeason(String season) {
  this.season = season;
 }

 /**
  * @return the badges
  */
 public String getBadges() {
  return badges;
 }

 /**
  * @param badges
  *            the badges to set
  */
 public void setBadges(String badges) {
  this.badges = badges;
 }

 /**
  * @return the ratingAvg
  */
 public double getRatingAvg() {
  return ratingAvg;
 }

 /**
  * @param ratingAvg
  *            the ratingAvg to set
  */
 public void setRatingAvg(double ratingAvg) {
  this.ratingAvg = ratingAvg;
 }

 /**
  * @return the ratingCount
  */
 public int getRatingCount() {
  return ratingCount;
 }

 /**
  * @param ratingCount
  *            the ratingCount to set
  */
 public void setRatingCount(int ratingCount) {
  this.ratingCount = ratingCount;
 }

 /**
  * @return the inventoryCount
  */
 public int getInventoryCount() {
  return inventoryCount;
 }

 /**
  * @param inventoryCount
  *            the inventoryCount to set
  */
 public void setInventoryCount(int inventoryCount) {
  this.inventoryCount = inventoryCount;
 }

 /**
  * @return the dateCreated
  */
 public String getDateCreated() {
  return dateCreated;
 }

 /**
  * @param dateCreated
  *            the dateCreated to set
  */
 public void setDateCreated(String dateCreated) {
  this.dateCreated = dateCreated;
 }

 /**
  * Overridden toString() method
  */
 @Override
 public String toString() {
  return "Product [productId=" + productId + ", sku=" + sku + ", name=" + name + ", productUrl=" + productUrl
    + ", price=" + price + ", retailPrice=" + retailPrice + ", thumbnailUrl=" + thumbnailUrl
    + ", searchKeywords=" + searchKeywords + ", description=" + description + ", category=" + category
    + ", categoryId=" + categoryId + ", brand=" + brand + ", childSku=" + childSku + ", childPrice="
    + childPrice + ", color=" + color + ", colorFamily=" + colorFamily + ", colorSwatches=" + colorSwatches
    + ", size=" + size + ", shoeSize=" + shoeSize + ", pantsSize=" + pantsSize + ", occassion=" + occassion
    + ", season=" + season + ", badges=" + badges + ", ratingAvg=" + ratingAvg + ", ratingCount="
    + ratingCount + ", inventoryCount=" + inventoryCount + ", dateCreated=" + dateCreated + "]";
 }

}

Configuring

Now build the maven package and install the bundle in ./system/console in AEM. After doing this - 
  • Navigate to the ./system/console/configMgr and search for Red Quark XML Reader config. Open it and end the required details (specific to your project) as below
Red Quark XML Reader
Here we have put in the cron expression, XML file path, XML URL and the JCR path to store the data. Please note that there is no "/" before content. If you wish to give "/" then you can change the code accordingly in our XMLWriterServiceImpl class.

Also, refer to the article in case you find some difficulty in running the scheduler.
  • Now, once the configuration is saved, XML data will be imported in JCR and will look like below
XML data imported in JCR

Conclusion

Congratulations!! 🙋 we have successfully imported XML data into JCR and I hope you enjoyed this post.

You can find the complete code of this project on my GitHub. Feel free to fork or open issues, if any.

I would love to hear your thoughts on this and would like to have suggestions from you to make it better. 

Feel free to befriend me on Facebook, Twitter or Linked In or say Hi by email.

Happy Coding 😃

Comments

Popular posts from this blog

Day 00: AEM Developer Series

Hello everyone! Welcome to this AEM development series. We can all see the revolution of Digital Marketing today. Companies are dying to be a part of it and they have made this a war for the Digital Marketing tools.
Adobe is way ahead in this war and has gained a lot of market capture. They are leaders in the Digital Marketing platforms since 2014-15. One of the flagship product in Adobe's Digital Marketing suite is Adobe Experience Manager (AEM).
Since AEM is in huge demand, the people who know how to develop on AEM are also in huge demand. But developing on AEM is not easy as it is made up of various open-source technologies such as Apache Felix (OSGi), Apache Sling, Apache Oak and Adobe's own technologies like Granite, HTL etc. Learning all these technologies in conjunction can sometimes become confusing and frustrating 😫.
When I first started learning AEM in 2016, I was dumbfounded to see there is so much going on under the hood. I then spent months to gather all the res…

Day 01: Introduction to AEM

Day 04: Developing first OSGi bundle