Converters and Populators

Before start to converters and populators , We need to understand DTO (Data transfer object). In the field of programming , we can describe DTO like "It is a object that used to encapsulate data, and transfer the data between classes and modules of your application". A DTO is helpful whenever you need to group values in ad hoc structures for passing data around. DTOs help to further decouple presentation from the service layer and the domain model. Data Transfer Objects (DTOs) are objects created to only contain values and have no business logic except for getter and setter methods

Using Converters, we will trying to create a target DTO by converting a source Model object and using Populators to populate the DTO. It means that Converters create new instances of Data objects and call Populators to populate these data objects.

In applications , we need to create a subset of data from a larger data structure. For example , we have customer table(CustomerModel) in the database with 30 fields but we required only 10 field of them to return to Front end(UI) or other API. We will fetch our customer model from the database as source and we will convert source customer model to target Customer DTO data structure which is subset of the customer model and will be passed customer DTO to UI. We will use converters and populators to create a target DTO by converting a source Model object using and Populators will populate data in DTO.

Converter

It creates new instances of Data objects and call Populators to populate data. It contains list of populators and uses populators to convert data from source to target. The Data object is always created from a prototype-scoped spring bean that is defined in the beans.xml file for the extension.

Populator

It fills the data object by getting the data from the model. It’s not recommended to call populator directly in code. We can , but it is not recommended by hybris. Because, we need to convert our model( ProductModel ) from multiple places. like PDP page, PLP page and order summary page etc. It would be batter to separate class to do this conversion.

converters and populators | Hybris

Implementation Flow

The below diagram present flow of program execution within SAP Commerce.

  • Application fetch data from DB via Dao and pass model to service layer.

  • Service layer called by façade layer and pass Model object to façade

  • Converters and populators are used in façade layer to convert the model to DTO.

  • In façade layer, we call converter method by injecting the converter bean. We call converter methods to convert the model to data.

  • Converter having list of populators. We can add the list of populators.

  • Populators used for get value from source model and set value in target and we call to converter method and Converter internally calls the list of populators.

Steps for implement Converters and Populators

1) Defining DTO (Data Transfer Object)

Hybris provide DTO generation via xml configuration. you will define bean and properties in <extensions>-beans.xml for create DTO class and build the hybris system. After successful build, you can check your DTO(data transfer object) class at the specified package and DTO class contains your new property.

For Example: MyUserData (DTO), we will define our façade extensions in trainingfacades-beans.xml. Hybris out-of-box, UserModel have many properties but we have required only name and id out of all. So, we will define DTO class in <extensions>-bean.xml file. It will contain only two properties like below.

<bean class="com.experts.hybris.training.facades.data.MyUserData">

<property name="id" type="String"/>

<property name="name" type="String"/>

</bean>

After successful build (ant all), Below MyUserData class will generate by hybris in plateform/bootstrap/gensrc folder.

package com.experts.hybris.training.facades.data;

import java.io.Serializable;


public class MyUserData implements Serializable

{

private static final long serialVersionUID = 1L;

private String id;

private String name;

public MyUserData()

{

// default constructor

}

public void setId(final String id)

{

this.id = id;

}

public String getId()

{

return id;

}

public void setName(final String name)

{

this.name = name;

}

public String getName()

{

return name;

}

}

2) Register Converter and Populator in Spring file

Now, we will define converter in <extensions>-spring.xml (trainingfacades-spring.xml) file. We will give convert bean id and define parent abstract class. AbstractPopulatingConverter class will populate converter that uses a list of configured populators to populate the target during conversion. We specify what our target object is (DTO).

<!--define Converter and populators in spring xml file -->

<bean id="myUserConverter" parent="abstractPopulatingConverter">

<property name="targetClass"

value="com.experts.hybris.training.facades.data.MyUserData" />

<property name="populators">

<list>

<ref bean="myUserDataPopulator" />

</list>

</property>

</bean>


3. Define Populator

Now we will create Populator. It implement the Populator<SOURCE,TARGET> interface and implement (override) the populate method. The populate method can be as simple as getting and setting values from the Model object (Source) to the target (DTO) or calling Services to get additional data.

package com.experts.hybris.training.facades.populators;


import de.hybris.platform.converters.Populator;

import de.hybris.platform.core.model.user.UserModel;

import de.hybris.platform.servicelayer.dto.converter.ConversionException;

import com.experts.hybris.training.facades.data.MyUserData;

/**

* @author shamsher.singh

*/

public class MyUserDataPopulator implements Populator<UserModel, MyUserData>

{


@Override

public void populate(final UserModel source, final MyUserData target) throws ConversionException

{

target.setId(source.getUid());

target.setName(source.getName());

}

}

We will register our populator in spring file (trainingfacades-spring.xml).

<bean id="myUserDataPopulator"

class="com.experts.hybris.training.facades.populators.MyUserDataPopulator">

</bean>

4. Calling the Convertor

We can call the converter’s covert method or the convertAll which invokes all the populators defined for that convertor in sequence. Below class , We simple created DefaultMyTestFacade class and call convertor in testMethod() which is return to final MyUserData. Now, we can use this DTO and send to third party or UI.

package com.experts.hybris.training.facades.suggestion.impl;


import de.hybris.platform.core.model.user.UserModel;

import de.hybris.platform.servicelayer.dto.converter.Converter;

import de.hybris.platform.servicelayer.user.UserService;


import org.springframework.beans.factory.annotation.Required;


import com.experts.hybris.training.facades.data.MyUserData;


public class DefaultMyTestFacade

{

private UserService userService;

private Converter<UserModel, MyUserData> myUserConverter;


public UserService getUserService()

{

return userService;

}

@Required

public void setUserService(final UserService userService)

{

this.userService = userService;

}

public Converter<UserModel, MyUserData> getMyUserConverter()

{

return myUserConverter;

}

@Required

public void setMyUserConverter(final Converter<UserModel, MyUserData> myUserConverter)

{

this.myUserConverter = myUserConverter;

}

public void testMethod()

{

final UserModel user = getUserService().getCurrentUser();

final MyUserData myUserData = myUserConverter.convert(user);

System.out.println("Name :" + myUserData.getName() + ",Uid :" + myUserData.getId());

}

}



We will register our main class defaultMyTestFacade in spring file (trainingfacades-spring.xml).

<bean id="defaultMyTestFacade"

class="com.experts.hybris.training.facades.suggestion.impl.DefaultMyTestFacade">

<property name="userService" ref="userService" />

<property name="myUserConverter" ref="myUserConverter" />

</bean>


In this example , the UserModel has been successfully converted into MyUserData DTO