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 -
- 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.
- 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.
- 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.
- 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.
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();
}
- 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");
}
}
}
}
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");
}
}
}
}
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 = -7423990858185520203 L;
// 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 = -2525852165658067914 L;
@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.
No comments:
Post a Comment
If you have any doubts or questions, please let us know.