Adding a New Attribute to Product and Serving It to Spartacus

Adding a New Attribute to Product and Serving It to Spartacus

When customizing SAP Commerce Cloud (Hybris), you may need to add new attributes to existing models like ProductModel and expose them to the Spartacus storefront. This guide will walk you through adding a new attribute to ProductModel and serving it to Spartacus.


Step 1: Add the New Attribute to ProductModel

Modify the Items.xml

Define the new attribute in the items.xml file of your extension:

1
2
3
4
5
6
7
8
<itemtype code="Product" autocreate="true" generate="true">
<attributes>
<attribute qualifier="newAttribute" type="java.lang.String">
<modifiers read="true" write="true" optional="true" />
<persistence type="property" />
</attribute>
</attributes>
</itemtype>

Run ant clean all to regenerate the model classes and update the database schema.


Step 2: Add the Attribute to Product Data

Update the ProductData Class

Add the new attribute to ProductData:

1
2
3
<bean class="de.hybris.platform.commercefacades.product.data.ProductData">
<property name="newAttribute" type="java.lang.String" />
</bean>

Step 3: Create a Populator for the New Attribute

Create a custom populator to populate ProductData with the value from ProductModel:

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.mycompany.core.populators;

import de.hybris.platform.commercefacades.product.converters.populator.AbstractProductPopulator;
import de.hybris.platform.core.model.product.ProductModel;
import de.hybris.platform.commercefacades.product.data.ProductData;

public class NewAttributePopulator extends AbstractProductPopulator<ProductModel, ProductData> {

@Override
public void populate(final ProductModel source, final ProductData target) {
target.setNewAttribute(source.getNewAttribute());
}
}

Step 4: Register the Populator in Spring Configuration

Add the populator to the productConverter in your Spring XML configuration:

1
2
3
4
5
6
7
8
9
10
<bean id="newAttributePopulator" class="com.mycompany.core.populators.NewAttributePopulator" />

<bean id="productConverter" class="de.hybris.platform.commercefacades.product.converters.impl.DefaultProductConverter">
<property name="populators">
<list>
<ref bean="newAttributePopulator" />
<!-- Other populators -->
</list>
</property>
</bean>

Step 5: Extend the Product Web Services

Update the ProductWsDTO to include the new attribute:

1
2
3
<bean class="de.hybris.platform.commercewebservicescommons.dto.product.ProductWsDTO">
<property name="newAttribute" type="String"/>
</bean>

Update the FieldSetLevelMapping to map the attribute from ProductData to ProductWsDTO:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<bean parent="fieldSetLevelMapping" id="productWsDTOFieldSetLevelMapping">
<property name="dtoClass"
value="de.hybris.platform.commercewebservicescommons.dto.product.ProductWsDTO"/>
<property name="levelMapping">
<map>
<entry key="BASIC"
value="purchasable,stock,name,baseProduct,availableForPickup,code,url,price,sapUnit,newAttribute"/>
<entry key="DEFAULT"
value="summary,averageRating,purchasable,stock(DEFAULT),description,variantMatrix(DEFAULT),name,baseOptions(DEFAULT),baseProduct,availableForPickup,variantOptions(DEFAULT),code,url,price(DEFAULT),numberOfReviews,manufacturer,categories(BASIC,name),priceRange,multidimensional,configuratorType,configurable,tags,sapAddToCartDisabled,sapAddToCartDisabledMessage,sapUnit,newAttribute"/>
<entry key="FULL"
value="summary,productReferences(FULL),classifications(FULL),averageRating,purchasable,volumePrices(FULL),variantType,stock(FULL),description,variantMatrix(FULL),name,baseOptions(FULL),baseProduct,availableForPickup,variantOptions(FULL),reviews(FULL),code,url,price(FULL),numberOfReviews,manufacturer,volumePricesFlag,futureStocks(FULL),images(FULL),categories(FULL),potentialPromotions(FULL),priceRange,multidimensional,configuratorType,configurable,tags,sapAddToCartDisabled,sapAddToCartDisabledMessage,sapUnit,newAttribute"/>
</map>
</property>
</bean>

Step 6: Extend the Occ Layer

Update the OCC controller to include the new attribute in the response:

1
2
3
4
5
6
@RequestMapping(value = "/{productCode}", method = RequestMethod.GET)
public ProductWsDTO getProductByCode(@PathVariable String productCode) {
ProductData productData = productFacade.getProductForCode(productCode);
ProductWsDTO productWsDTO = mapper.map(productData, productWsDTO);
return productWsDTO;
}

Step 7: Update Spartacus to Consume the New Attribute

Modify the Spartacus product model to include the new attribute:

1
2
3
4
5
export interface Product {
code?: string;
name?: string;
newAttribute?: string;
}

Update the UI components to display the attribute:

1
2
3
<div *ngIf="product?.newAttribute">
<p>{{ product.newAttribute }}</p>
</div>

Testing

  1. Backend: Ensure the attribute is added to the database and populated correctly.
  2. API: Verify that the OCC endpoint includes the new attribute.
  3. Frontend: Test that Spartacus displays the new attribute as expected.

Final Thoughts

By following these steps, you can successfully add new attributes to SAP Commerce and expose them to Spartacus. This approach ensures maintainability and scalability for future customizations.

Happy Coding!