CRM and CX Blog Posts by SAP
cancel
Showing results for 
Search instead for 
Did you mean: 
joris_quenee
Product and Topic Expert
Product and Topic Expert
2,439

Introduction

Natively Composable Storefront / SAP Commerce Cloud doesn't support dynamic configuration. The only exception is regarding OCC EndPoint : OCC_BACKEND_BASE_URL_VALUE

And it is well known issue in Spartacus : https://github.com/SAP/spartacus/issues/5772

This article will explain how we can easily extend SAP Commerce Cloud and Composable Storefront to fill this gap. As example, we will use SAP CDC integration.

 

SAP Commerce

First thing is to extend OCC API BaseSite to enrich output with additional settings: occ/v2/basesites?fields=BASIC / BaseSitesController.getBaseSites()

For that, you need to create two custom extensions one for the core and for occ

 

Core extension

In custom core extensions, you need to extend BaseSite item to record CDC settings (*items.xml)

<itemtype code="BaseSite" autocreate="false" generate="false">
<attributes>
 <attribute type="java.lang.String" qualifier="cdcJavascriptUrl">
  <persistence type="property" />
  <modifiers optional="false" />
  <description>CDC EndPoint with API Key</description>
</attribute>

<attribute type="int" qualifier="cdcSessionExpiration">
 <persistence type="property" />
 <modifiers optional="false" />
 <description>CDC session expiration time in seconds</description>
</attribute>
</attributes>
</itemtype>

  Then Data and WsDTO beans need to be extended too (*beans.xml)

<bean class="de.hybris.platform.commercefacades.basesite.data.BaseSiteData">
 <property name="cdcJavascriptUrl" type="String"/>
 <property name="cdcSessionExpiration" type="Integer"/>
</bean>

<bean class="de.hybris.platform.commercewebservicescommons.dto.basesite.BaseSiteWsDTO">
 <property name="cdcJavascriptUrl" type="java.lang.String">
 <description>Indicates CDC EndPoint with API Key</description>
 </property>
 <property name="cdcSessionExpiration" type="java.lang.Integer">
 <description>Indicates CDC Session Expiration time</description>
 </property>
</bean>

A new Populator should be introduced to add new settings in Data object (*spring.xml)

<bean id="cdcBaseSitePopulator" class="com.basesite.populator.CDCBaseSitePopulator"></bean>

<bean parent="modifyPopulatorList">
 <property name="list" ref="baseSiteConverter" />
 <property name="add" ref="cdcBaseSitePopulator" />	
</bean>

Popular implementation should look like to this

public class CDCBaseSitePopulator implements Populator<BaseSiteModel, BaseSiteData> {

@Override
public void populate(final BaseSiteModel source, final BaseSiteData target) throws ConversionException {
 target.setCdcJavascriptUrl(source.getCdcJavascriptUrl());
 target.setCdcSessionExpiration(source.getCdcSessionExpiration());
 }
}

To influence correctly Spring configuration, custom core must depend on commercefacades extension (extensioninfo.xml)

<requires-extension name="commercefacades"/>

 

OCC extension

OCC extension should be created according official documentation. The purpose is to extend WsDTO mapping for including additional CDC settings.

In /occ/v2/*occ/web/spring/*-web-spring.xml file, you can declare this following additional attributes

<!-- It extends baseSiteWsDTOFieldSetLevelMapping bean from commercewebservices -->
<bean parent="fieldSetLevelMapping" id="cdcSiteWsDTOFieldSetLevelMapping">
 <property name="dtoClass" value="de.hybris.platform.commercewebservicescommons.dto.basesite.BaseSiteWsDTO"/>
 <property name="levelMapping">
 <map merge="true">
 <entry key="BASIC"
	value="cdcJavascriptUrl,cdcSessionExpiration"/>
 </map>
</property>
</bean>

 

Testing

After this customisation, you can compile and startup SAP Commerce Cloud. Then, you should connect to BackOffice for setting up the CDC settings in WCMS

Screenshot 2025-09-02 at 14.41.55.png

Following that, you should be able to see the result by call OCC API BaseSite : https://localhost:9002/occ/v2/basesites?fields=BASIC

...
<baseSites>
<cdcJavascriptUrl>JS_SDK_URL_PLACEHOLDER_ELEC</cdcJavascriptUrl>
<cdcSessionExpiration>3600</cdcSessionExpiration>
<channel>B2C</channel>
<isolated>false</isolated>
<name>Spartacus Electronics Site</name>
<uid>electronics-spa</uid>
</baseSites>
</baseSiteList>

 

Composable Storefront

In client side, several things must be customised :

  • BaseSite POJO class needs to be extended
  • CdcConfig class needs to be override
  • Cdc configuration has to be dynamically loaded

Type augmentation is clearly documented over here : https://sap.github.io/spartacus-docs/type-augmentation/

CDC dynamic loading can be executed by overriding static CdcConfig through Angular provider

Let first create a new module cdc.feature.module.ts that will inject CDC dynamic loading class

@NgModule({
  declarations: [],
  imports: [CdcRootModule],
  providers: [
    {
        provide: CdcConfig,
        useClass: DynamicCdcConfig
    },
    provideConfig({
      featureModules: {
        [CDC_FEATURE]: {
          module: () => import('@spartacus/cdc').then((m) => m.CdcModule),
        },
      },
    })
  ],
})

export class CdcFeatureModule {}

DynamicCdcConfig class should look like this

import { BaseSiteService } from "@spartacus/core";
declare module '@spartacus/core' {
    interface BaseSite {
      cdcJavascriptUrl?: string,
      cdcSessionExpiration?: number
    }
  }

@Injectable()
export class DynamicCdcConfig extends CdcConfig {
    
    constructor(protected baseSiteService: BaseSiteService) { 
        super();
        this.baseSiteService
          .getActive()
          .subscribe((currentBasesite) => (
            this.baseSiteService.get(currentBasesite).subscribe((value) => (
                this.cdc = [
                  {
                    baseSite: currentBasesite,
                    javascriptUrl: value?.cdcJavascriptUrl as string,
                    sessionExpiration: value?.cdcSessionExpiration as number,
                  }
                ]
              ))
        ));
    }
}

 Then new module must be imported in app.module.ts to be loaded at startup

@NgModule({
  declarations: [
    AppComponent,
    StaticPageComponent
  ],
  imports: [
    BrowserModule,
    StoreModule.forRoot({}),
    AppRoutingModule,
    EffectsModule.forRoot([]),
    SpartacusModule,
    CdcFeatureModule
  ],
  providers: [provideHttpClient(withFetch(), withInterceptorsFromDi()),],
  bootstrap: [AppComponent]
})
export class AppModule {}

 

Conclusion

As we saw, specific configuration by environment can be easily implemented in Composable Storefront. But If you need more support, please don't hesitate to contact SAP Expert Services.

1 Comment
tanvi_singhal
Participant
0 Kudos

Great post. A quick question. How do you handle environment-specific configs (API endpoints, feature flags, payment options) in a composable storefront with SAP Commerce without risking drift or cross-environment leakage?