How to create data transfer object(DTO), Converter and populator, Facade?

In this blog, we will explain the process of creating a data transfer object(DTO), Converter and populator, facade. We will show you the process of calling facade from the controller class and defining spring bean and its properties. We will create one model attribute and populate it. We will modify the UI by making a change in the tag file.

We take one example and this example explains how to show cart subtotal without taxes. Remember that there are many other ways by which we can show cart subtotal without taxes but we took the following approach to explain the above points.

Show cart subtotal without taxes/How to show cart subtotal without taxes?

Currently in SAP Hybris Commerce Accelerator when we add products to the cart then it shows cart subtotal with taxes. You can observe this in below image where we added one product to the cart in the apparel storefront that shows cart subtotal with taxes.

cart subtotal with taxes

Now here our goal is to show cart subtotal without including taxes. To achieve this goal we do not make any changes in OOB(out of the box) files but we use them from our created custom files to achieve this goal. We need to follow the following steps to achieve this goal.

  1. Create data transfer object(DTO)
  2. Create converter and populator
  3. Create facade and populate the data
  4. Call the facade from CartPageController/ Modify CartPageController
  5. Modify the cartTotal.tag file

1. Create data transfer object(DTO)

Now we will create one DTO(data transfer object) class named as SubTotalWithOutTax and it contains one property called as a sub of PriceData type. This sub property will hold the value of order subtotal without taxes.

Steps to create SubTotalWithOutTax DTO class

  1. Navigate to yacceleratorfacades->resources and open yacceleratorfacades-beans.xml.
  2. Add the following lines of code to yacceleratorfacades-beans.xml file.
    SubTotalWithOutTax DTO class
    Note: This entry must be between <beans> </beans> tag.
  3. Build the hybris system by running ant clean all.
    After successful build we can check our SubTotalWithOutTax DTO(data transfer object) class at the specified package and the file will look like this.

    SubTotalWithOutTax.java
    SubTotalWithOutTax.java

     

2. Create converter and populator

Before learning how to create converter and populator we need to know why we need converters and populators?

Now we will create a converter and populator for our SubTotalWithOutTax DTO(data transfer object) class. We need to follow the following steps to create a converter and populator.

  1. Now we create SubTotalWithOutTaxPopulator to fill the data in SubTotalWithOutTax DTO(data transfer object) class as you can see in the below image. SubTotalWithOutTaxPopulator implements the Populator interface.
    SubTotalWithOutTaxPopulator.java
    SubTotalWithOutTaxPopulator.java

     

  2. Navigate to yacceleratorfacades->resources and open yacceleratorfacades-spring.xml. Now we define a spring bean for the new SubTotalWithOutTaxPopulator and SubTotalWithOutTaxConverter as shown in below image.
    yacceleratorfacades-spring.xml
    yacceleratorfacades-spring.xml

     

  3. Build the hybris system by running ant clean all.

3. Create facade and populate the data

Generally, facade classes are created to call the services and to fill the data in DTO(data transfer object) class using converters and populators.

In our case, we create one DefaultBitbyteCartFacade class that implements BitbyteCartFacade interface. Through this class, we make a call to CartService and populate the data in SubTotalWithOutTax DTO class using converter and populator.

We need to follow the following steps to create BitbyteCartFacade

  1. Navigate to yacceleratorfacades->src and create an interface named as BitbyteCartFacade. as you can see in the below image

    BitbyteCartFacade.java
    BitbyteCartFacade.java
  2. Now we provide the implementation for the BibyteCartFacade interface in DefaultBitbyteCartFacade class.

    DefaultBitbyteCartFacade.java
    DefaultBitbyteCartFacade.java
  3. Navigate to yacceleratorfacades/resources and open yacceleratorfacades-spring.xml. Now we define a spring bean for the new DefaultBitbyteCartFacade as shown in below image.

    Spring Bean for Facade
    yacceleratorfacades-spring.xml
  4. Build the hybris system by running ant clean all.

4. Call the facade from CartPageController/Modify CartPageController

CartPageController is permitted to use annotation-based declaration so we inject BitbyteCartFacade as shown below in CartPageController.

BitbyteCartFacade bean Injection
CartPageController.java

Now add following lines of code inside prepareDataForPage method

Setting Model Attribute
CartPageController.java

Build the hybris system by running ant clean all.

5. Modify the cartTotal.tag file

Navigate to yacceleratorstorefront->web->webroot->WEB-INF->tags->cart and open cartTotal.tag file.

Replace the following lines of code with line number 14 and 15 to this file as shown in the image.

cartTotals.tag
cartTotals.tag

After saving this file, refresh apparel storefront and you can clearly observe that subtotal of the cart does not include taxes.

Cart Subtotal Without Taxes

What is the use ProductOption Enum in Hybris?

Products are core to any commerce. This is the product which drives the whole business and workflow associated with it. Be it procurement, inventory management, Media management, order management, fulfillment to name a few. Everything revolves around Product.

Essentially, this leads to having hundreds of attribute associated with products. Price, Stock , promotion, categories are few data set attached to product. Since not every page will want to have every data set to be populated. This is also not efficient to propagate all data sets to front layer.

Product Option is an Enum, which categorize hundreds of attribute of products into few data sets. For example attribute related to stocks (stock level, stock status) will be under Stock data set. Now the population of Product data will be done on the required data sets of Product Option Enum.

Take the example of Order history page, here we don’t want user to see stock data, product reviews, product delivery modes. So it is useless to populate these data sets.

 

Hybris provides a Bean class DefaultModifableConfigurablePopulator, which takes a Map of populators as one of the property. This map will contain Product Option enum as the key and corresponding populator bean id as the value.

 

<alias name="defaultProductConfiguredPopulator" alias="productConfiguredPopulator"/>
<bean id="defaultProductConfiguredPopulator" class="de.hybris.platform.commercefacades.converter.impl.DefaultConfigurablePopulator" >
<property name="populators">
<map key-type="de.hybris.platform.commercefacades.product.ProductOption">
<entry key="BASIC" value-ref="productBasicPopulatorList"/>
<entry key="PRICE" value-ref="productPricePopulatorList"/>
<entry key="PRICE_RANGE" value-ref="productPriceRangePopulator"/>
<entry key="GALLERY" value-ref="productGalleryPopulatorList"/>
<entry key="SUMMARY" value-ref="productSummaryPopulatorList"/>
<entry key="DESCRIPTION" value-ref="productDescriptionPopulatorList"/>
<entry key="CATEGORIES" value-ref="productCategoriesPopulatorList"/>
<entry key="PROMOTIONS" value-ref="productPromotionsPopulatorList"/>
<entry key="STOCK" value-ref="productStockPopulatorList"/>
<entry key="REVIEW" value-ref="productReviewPopulatorList"/>
<entry key="CLASSIFICATION" value-ref="productClassificationPopulatorList"/>
<entry key="VARIANT_FULL" value-ref="productVariantFullPopulatorList"/>
<entry key="REFERENCES" value-ref="productReferencesPopulator"/>
<entry key="DELIVERY_MODE_AVAILABILITY" value-ref="productDeliveryModeAvailabilityPopulator"/>
</map>
</property>
</bean>

 

If You want to add a new populator to the system, for example say video.

<enum class="de.hybris.platform.commercefacades.product.ProductOption">
<value>VIDEO</value>
</enum>

 

Now redefine the configureable populator bean to include your populator. Now the product data will start having your data set as well.

<alias name="videoProductConfiguredPopulator" alias="productConfiguredPopulator"/>
<bean id="myProductConfiguredPopulator" parent="defaultProductConfiguredPopulator">
    <property name="populators">
        <map key-type="com.myproject.facades.product.MyProductOption" merge="true">
            <entry key="Video" value-ref="videoOptionPopulator"/>
        </map>
    </property>
</bean>
 

 

 

Why we have converters and populators in hybris?

I can convert my models to DTO directly in facade layer. Then why should i have a converter?

Its Simple. We may need to convert a product (model) from multiple places. We convert it on product listing page, product detail page, order confirmation page etc. Hybris follows oops concept..So it is good to have a separate class to do this conversion for us, from all of these places.

Converters creates an object of DTO. While populators breaks the code for filling up data in DTO. This is required because, not each DTO needs all attributes of a model. Thus by having multiple populators, we can write more efficient code. Reverse populators are used to fill data in model from DTOs.

blog1

The image shows two paths followed (a and b) by two different facades using same converter and different poplators.

We should always use spring injected converters and  populators.