Sunday, April 24, 2022

AEM and Magento Integration Using Commerce Integration Framework(CIF) — Local Setup (Part1)

 The AEM and Magento are integrated using the Commerce Integration Framework (CIF); the CIF framework enables AEM to access magneto commerce instances through GraphQL API.

In this post series, let us see how to set up local Magento and AEM platforms and enable the CIF framework in AEM to integrate with Magento to build the storefront in AEM.

Let us start with setting up a local Magento instance.

I am going to use XAMPP on windows to enable the Magento servers.

Install Elastic search:

The latest Magento version requires Elasticsearch or OpenSearch for indexing but not support MySQL indexing.

Installed elastic search 7.17.3, https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.17.3-windows-x86_64.zip

You will see the below screen on successful installation

Download and Install XAMPP:

As a first step, download and install the XAMPP server, including Apache, PHP, MySQL, and PHP admin.

Now you should be able to manage the Apache and MySQL servers through the XAMPP control panel.

Start MySQL and Apache servers

Install Composer:

Install composer — A Dependency Manager for PHP, downloaded the latest version(v2.3.5) from https://getcomposer.org/download/.

Select PHP under XAMPP

Change the MySQL admin password:

Click on Shell in the XAMPP control panel

Execute mysqladmin -u root password — Enter the admin password

Add the new password to the config.inc.php file for auto-login

Create a Magento database:

Create a new database(e.g., magento2) for Magento, login to http://localhost/phpmyadmin/

Enable Required Extensions:

Enable the below extensions on the php.ini file (to enable removing the semicolon from the extension)

extension=gd
extension=intl
extension=soap
extension=sockets
extension=sodium
extension=xsl

Enable VirtualHost for the Magento Pub folder:

Enable the below virtual hosts to C:\xampp\apache\conf\extra\httpd-vhosts.conf (change the server name accordingly)

<VirtualHost *:80>
DocumentRoot “C:/xampp/htdocs/magento/pub”
ServerName albin.magento.com
</VirtualHost>
<VirtualHost *:80>
DocumentRoot “C:/xampp/htdocs”
ServerName localhost
</VirtualHost>

Add the below entry to C:\Windows\System32\drivers\etc\hosts file to support the local domain, e.g., albin.magento.com

127.0.0.1 albin.magento.com

Download Magento:

Download Magento( v 2.4.4) within Apache htdocs folder

composer create-project --repository-url=https://repo.magento.com/ magento/project-community-edition:2.4.4 C:\xampp\htdocs\magento

On completion, this will download Magento into C:\xampp\htdocs\magento directory

Setup authentication for Magento repo:

We should enable the Magento repository authentication before downloading the Magento software.

Create a file with the name auth.json under C:\xampp\htdocs\magento and add the below content

{
“bitbucket-oauth”: {},
“github-oauth”: {},
“gitlab-oauth”: {},
“gitlab-token”: {},
“http-basic”: {
“repo.magento.com”: {
“username”: “<public-key>”,
“password”: “<private-key>”
}
},
“bearer”: {}
}

To generate the keys, login to https://marketplace.magento.com/ (register for an account if not already)

Create A New Access Key — Enter a name, and copy the generated private and public keys.

Install Magento:

Execute the below command from the magneto root folder C:\xampp\htdocs\magento change the DB name, password, and base URL accordingly)

php bin/magento setup:install --base-url="http://albin.magento.com/" --db-host="localhost" --db-name="magento2" --db-user="root" --db-password="magento" --admin-firstname="admin" --admin-lastname="admin" --admin-email="[email protected]" --admin-user="admin" --admin-password="Admin123!" --language="en_US" --currency="USD" --timezone="America/Chicago" --use-rewrites="1" --backend-frontname="admin" --search-engine=elasticsearch7 --elasticsearch-host="localhost" --elasticsearch-port=9200

You may encounter the below issue during the installation

To resolve the issue, replace validateURLScheme function in C:\xampp\htdocs\magento\vendor\magento\framework\Image\Adapter\Gd2.php file with the below one

private function validateURLScheme(string $filename) : bool
{
$allowed_schemes = [‘ftp’, ‘ftps’, ‘http’, ‘https’];
$url = parse_url($filename);
if ($url && isset($url[‘scheme’]) && !in_array($url[‘scheme’], $allowed_schemes)
&& !file_exists($filename)) {
return false;
}
return true;
}

Rerun the install command — you will see the “Magento installation complete” message.

Restart the Apache server through the XAMPP control panel and access the storefront → albin.magento.com

You may see the below broken experience

To fix that

Go to: C:\xampp\htdocs\magento\vendor\magento\framework\View\Element\Template\File\Validator.phpReplace — $realPath = $this->fileDriver->getRealPath($path);with the below code and save the file$realPath = str_replace(‘\\’, ‘/’, $this->fileDriver->getRealPath($path));

Go to C:\xampp\htdocs\magento\app\etc\di.xml
Replace Magento\Framework\App\View\Asset\MaterializationStrategy\Symlink with Magento\Framework\App\View\Asset\MaterializationStrategy\Copy

Execute the below commands

php bin/magento indexer:reindex
php bin/magento setup:upgrade
php bin/magento setup:static-content:deploy -f
php bin/magento cache:flush

Install sample data:

Install the latest sample data — Execute the below commands

php bin/magento sampledata:deploy
php bin/magento indexer:reindex
php bin/magento setup:upgrade
php bin/magento setup:static-content:deploy -f
php bin/magento cache:flush

Now access the storefront URL and admin console

http://albin.magento.com

http://albin.magento.com/admin (admin/<password specified while installation)

You may receive the below exception while accessing the admin console

To fix the issue, disable the Two factor authentication

php bin/magento module:disable Magento_TwoFactorAuth

You can now add products to your cart and checkout.

Track order from admin console — http://albin.magento.com/admin

Sales →Orders

GraphQL API:

The Magento data is also accessible through GraphQL API to enable the headless ecommerce experiences — the URL to access the GraphQL endpoint is http://albin.magento.com/graphql

e.g., API to fetch specific product SKU data

{
storeConfig {
store_code
store_name
is_default_store
store_group_code
is_default_store_group
locale
base_currency_code
default_display_currency_code
timezone
weight_unit
base_url
base_link_url
base_static_url
base_media_url
secure_base_url
secure_base_link_url
secure_base_static_url
secure_base_media_url
}
}

I am using the Altair GraphQL Chrome plugin to test the API(use any GraphQL client.

The Local Magento platform is ready to support the headless eCommerce experience from the AEM storefront; in the next post, let us see how to enable the AEM CIF framework to build the headless eCommerce experience between AEM and Magento.

Thursday, April 21, 2022

Apache not starting - XAMPP on Windows

I was facing an issue while starting the Apache Server running in XAMPP on the Windows system; the server was not starting from the XAMPP control panel but was able to start the server directly by running the httpd.exe.

The start task was struck while doing through the XAMPP control panel

Also, was seeing the below exception in the error log.

VirtualProtect() failed [87] The parameter is incorrect

Port 80 was not in use; some configuration changes did not help.

Finally, the issue was due to the existing service entry for Apache2.4.


Properties



The service was created as part of the Bitnami WordPress installation and was not removed on uninstallation.

To resolve the issue, remove the Apace2.4 service entry.

Run the below command as an administrator through the command line

sc delete "Apache2.4."


Create a new service entry for the XAMPP Apache server

Run apache_installservice.bat from xampp/apache folder - this will create a new Apache2.4 service pointing to the XAMPP apache server



Now the Apache server can be managed through the XAMPP control panel.



Monday, April 11, 2022

What are Custom HTML Elements? | How to use Custom HTML Elements in AEM?

 In this post, let us explore what Custom HTML Elements are and how to use Custom HTML Elements in AEM.

Custom Elements allow web developers to define new types of HTML elements.Once a custom element is defined, we can use it on par with built-in HTML elements.

Some of the important features are enabled by Custom HTML elements.

  • Define new HTML/DOM elements
  • Create elements that extend from other elements
  • Logically bundle together custom functionality into a single tag
  • Extend the API of existing DOM elements

Web Components uses Custom HTML Elements as one of the building blocks to enable reusable custom elements(Components).

Rules on creating custom elements:

  • The name of a custom element must contain a dash (-). So <my-element>, and <my-awesome-app> are valid names.
  • You can’t register the same tag more than once. Attempting to do so will throw a DOMException
  • Custom elements cannot be self-closing(<my-element/>), Always write a closing tag <my-element> </my-element>

Steps for creating Custom HTML Elements:

  • Define a custom element e.g. <my-element> </my-element>
  • Create a class with special methods.
class MyElement extends HTMLElement {
constructor() {
super();
// element created
}
connectedCallback() {
// browser calls this method when the element is added to the document
// (can be called many times if an element is repeatedly added/removed)
}
disconnectedCallback() {
// browser calls this method when the element is removed from the document
// (can be called many times if an element is repeatedly added/removed)
}
static get observedAttributes() {
return [/* array of attribute names to monitor for changes */];
}
attributeChangedCallback(name, oldValue, newValue) {
// called when one of attributes listed above is modified
}
adoptedCallback() {
// called when the element is moved to a new document
// (happens in document.adoptNode, very rarely used)
}
// there can be other element methods and properties
}

Register the element:

// let the browser know that <my-element> is served by our new class customElements.define("my-element", MyElement);

Refer to https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements and https://web.dev/custom-elements-v1/ for more details.

Let us quickly see how to create Custom HTML Elements to format the data in HTML.

<time-formatted> </time-formatted>

Attributes(datetime and the other formating options for Intl.DateTimeFormat):

datetime
year
month
day
hour
minute
second
time-zone-name
<html>
<head>
<script>
class TimeFormatted extends HTMLElement { // Class to handle custom elements functionality
connectedCallback() {

let date = new Date(this.getAttribute('datetime') || Date.now());
this.innerHTML = new Intl.DateTimeFormat("default", {
year: this.getAttribute('year') || undefined,
month: this.getAttribute('month') || undefined,
day: this.getAttribute('day') || undefined,
hour: this.getAttribute('hour') || undefined,
minute: this.getAttribute('minute') || undefined,
second: this.getAttribute('second') || undefined,
timeZoneName: this.getAttribute('time-zone-name') || undefined,
}).format(date);
}
}
customElements.define("time-formatted", TimeFormatted); //Register custom HTML Element
</script>
</head>
<body>
<time-formatted datetime="2022-04-11"
year="numeric" month="long" day="numeric"
hour="numeric" minute="numeric" second="numeric"
time-zone-name="short"></time-formatted>
</body>
</html>

The formatted data is now displayed on the web page through custom elements and the specified attributes.

We can extend the Custom Element and the class to use additional callback methods and functionalities.

Let us quickly see how to enable the same custom elements to AEM.

Create a client library(e.g., wknd.site.custom-time-element) with the required JS

class TimeFormatted extends HTMLElement { // Class to handle custom elements functionalityconnectedCallback() {

let date = new Date(this.getAttribute('datetime') || Date.now());
this.innerHTML = new Intl.DateTimeFormat("default", {
year: this.getAttribute('year') || undefined,
month: this.getAttribute('month') || undefined,
day: this.getAttribute('day') || undefined,
hour: this.getAttribute('hour') || undefined,
minute: this.getAttribute('minute') || undefined,
second: this.getAttribute('second') || undefined,
timeZoneName: this.getAttribute('time-zone-name') || undefined,
}).format(date);
}
}
customElements.define("time-formatted", TimeFormatted); //Register custom HTML Element

Embed the new client library as part of the site level client library

Create a Component to enable the custom element

<p> Custom Element - Time Formater </p><time-formatted datetime=${properties.datetime}
year=${properties.yearformat} month=${properties.monthformat} day=${properties.dayformat}
hour=${properties.hourformat} minute=${properties.minuteformat} second=${properties.seconfformat}
time-zone-name=${properties.timezonename}></time-formatted>

Create the required dialogs to enable the needed configuration attributes for the custom element.

Now author the component to the required page. The user will now see the formatted data on the web page.

Maybe in the next post, let us see more on web components with additional features.ou cannot applaud your own story