Migrating from Accelerator to Composable Storefront: A Technical Roadmap for Enterprises

If you’re reading this, you’re probably wondering whether it’s time to move from your SAP Commerce Accelerator to Composable Storefront. Maybe your front-end team is frustrated with JSP templates, or you need better mobile experience. Let me walk you through what this migration actually looks like, based on real experience.

Why Migrate?

What you’re leaving behind:

Server-side JSP renderingTightly coupled front-end and back-endLimited mobile experience

What you’re getting:

Modern Angular-based SPADecoupled architecture via OCC APIsBetter performance with SSRIndependent front-end deployment

The catch? You’re moving from monolithic to microservices-style architecture. Your team needs JavaScript/TypeScript skills.

Step 1: Assessment

Start by cataloging your customizations:

# Find custom JSP files
find web/webroot/WEB-INF/views -name “*.jsp” | grep -v “/yacceleratorstorefront/”

# Custom controllers
grep -r “@Controller” –include=”*Controller.java” | grep -v “de.hybris.platform”

Create a spreadsheet with every customization. This becomes your migration backlog.

Step 2: Build OCC Foundation

You need to expose everything via OCC APIs first. Here’s a quick example for custom product data:

// Custom WsDTO
@ApiModel(value = “customProduct”)
public class CustomProductWsDTO extends ProductWsDTO {
private String warrantyInfo;
private String installationGuideUrl;
// getters/setters
}

// Populator
public class CustomProductPopulator implements Populator<ProductModel, CustomProductWsDTO> {
@Override
public void populate(ProductModel source, CustomProductWsDTO target) {
target.setWarrantyInfo(source.getWarrantyInfo());
target.setInstallationGuideUrl(source.getInstallationGuideUrl());
}
}

For custom business logic, create OCC endpoints:

@Controller
@RequestMapping(value = “/{baseSiteId}/custom”)
public class CustomOccController {

@GetMapping(“/products/{productCode}/compatibility”)
@ResponseBody
public CompatibilityWsDTO checkCompatibility(
@PathVariable String productCode,
@RequestParam String customerProductId) {

CompatibilityData data = customProductFacade
.checkProductCompatibility(productCode, customerProductId);
return dataMapper.map(data, CompatibilityWsDTO.class);
}
}

Step 3: Setup Composable Storefront

# Install and setup
ng new my-storefront
cd my-storefront
ng add @spartacus/schematics –base-site=electronics –base-url=https://localhost:9002

Configure your endpoints:

// spartacus-configuration.module.ts
provideConfig({
backend: {
occ: {
baseUrl: environment.occBaseUrl,
prefix: ‘/occ/v2/’,
endpoints: {
product: ‘products/${productCode}?fields=DEFAULT,warrantyInfo’,
productCompatibility: ‘custom/products/${productCode}/compatibility’
}
}
},
context: {
baseSite: [‘electronics’],
currency: [‘USD’],
language: [‘en’]
}
})

Step 4: Migrate Components

Here’s a real migration example.

Old Accelerator JSP:

<div class=”product-detail”>
<h1>${product.name}</h1>
<div class=”warranty-info”>
<strong>Warranty:</strong> ${product.warrantyInfo}
</div>
</div>

New Angular Component:

// custom-product-detail.component.ts
@Component({
selector: ‘app-custom-product-detail’,
templateUrl: ‘./custom-product-detail.component.html’
})
export class CustomProductDetailComponent implements OnInit {
product$: Observable<CustomProduct>;

constructor(
private currentProductService: CurrentProductService,
private customProductService: CustomProductService
) {}

ngOnInit(): void {
this.product$ = this.customProductService.getCustomProduct();
}
}<!– custom-product-detail.component.html –>
<div *ngIf=”product$ | async as product”>
<h1>{{ product.name }}</h1>
<div *ngIf=”product.warrantyInfo”>
<strong>{{ ‘product.warranty’ | cxTranslate }}:</strong>
<p>{{ product.warrantyInfo }}</p>
</div>
</div>

Replace default Spartacus components via config:

provideConfig({
cmsComponents: {
ProductDetailsTabComponent: {
component: CustomProductDetailComponent
}
}
})

Step 5: Checkout

Adding custom checkout steps is straightforward:

// Custom step configuration
export const customCheckoutSteps = [
{
id: ‘deliveryAddress’,
name: ‘checkoutProgress.deliveryAddress’,
routeName: ‘checkoutDeliveryAddress’,
type: [CheckoutStepType.DELIVERY_ADDRESS]
},
{
id: ‘giftMessage’, // Your custom step
name: ‘checkoutProgress.giftMessage’,
routeName: ‘checkoutGiftMessage’,
type: [CheckoutStepType.PAYMENT_DETAILS]
},
// … more steps
];

Step 6: SSR Setup

ng add @spartacus/setup –ssr

Add caching for better performance:

// server.ts
const cache = new LRU({
max: 100,
ttl: 1000 * 60 * 60 // 1 hour
});

app.engine(‘html’, (filePath, options, callback) => {
const cacheKey = options.req.url;
const cachedHtml = cache.get(cacheKey);

if (cachedHtml) {
return callback(null, cachedHtml);
}

ngExpressEngine({ bootstrap: AppServerModule })(filePath, options, (err, html) => {
if (!err && html) cache.set(cacheKey, html);
callback(err, html);
});
});

Step 7: Deploy

npm run build:ssr

Simple Kubernetes deployment:

apiVersion: apps/v1
kind: Deployment
metadata:
name: composable-storefront
spec:
replicas: 3
template:
spec:
containers:
– name: storefront-ssr
image: your-registry/composable-storefront:latest
ports:
– containerPort: 4000
env:
– name: OCC_BASE_URL
value: “https://your-commerce-backend.com”

Common Issues & Quick Fixes

CORS errors?

# local.properties
corsfilter.commercewebservices.allowedOrigins=http://localhost:4200

Random logouts?

provideConfig({
session: { synchronization: true }
})

Translations not working? Structure your i18n files properly:

// assets/i18n/en/product.json
{
“product”: {
“warranty”: “Warranty”,
“downloadGuide”: “Download Guide”
}
}

My Advice

Don’t try to migrate everything at once. Start with one section, test thoroughly, then expand. The Composable Storefront is actively maintained by SAP, so you’re not just modernizing—you’re joining an ecosystem that keeps evolving.

The migration is substantial but worth it. Your team gets modern tooling, faster deployments, and better customer experience.

Resources

Composable Storefront DocsOCC API ReferenceSAP Community

What’s been your biggest challenge with this migration? Share in the comments!

 

​ If you’re reading this, you’re probably wondering whether it’s time to move from your SAP Commerce Accelerator to Composable Storefront. Maybe your front-end team is frustrated with JSP templates, or you need better mobile experience. Let me walk you through what this migration actually looks like, based on real experience.Why Migrate?What you’re leaving behind:Server-side JSP renderingTightly coupled front-end and back-endLimited mobile experienceWhat you’re getting:Modern Angular-based SPADecoupled architecture via OCC APIsBetter performance with SSRIndependent front-end deploymentThe catch? You’re moving from monolithic to microservices-style architecture. Your team needs JavaScript/TypeScript skills.Step 1: AssessmentStart by cataloging your customizations:# Find custom JSP files
find web/webroot/WEB-INF/views -name “*.jsp” | grep -v “/yacceleratorstorefront/”

# Custom controllers
grep -r “@Controller” –include=”*Controller.java” | grep -v “de.hybris.platform”Create a spreadsheet with every customization. This becomes your migration backlog.Step 2: Build OCC FoundationYou need to expose everything via OCC APIs first. Here’s a quick example for custom product data:// Custom WsDTO
@ApiModel(value = “customProduct”)
public class CustomProductWsDTO extends ProductWsDTO {
private String warrantyInfo;
private String installationGuideUrl;
// getters/setters
}

// Populator
public class CustomProductPopulator implements Populator<ProductModel, CustomProductWsDTO> {
@Override
public void populate(ProductModel source, CustomProductWsDTO target) {
target.setWarrantyInfo(source.getWarrantyInfo());
target.setInstallationGuideUrl(source.getInstallationGuideUrl());
}
}For custom business logic, create OCC endpoints:@Controller
@RequestMapping(value = “/{baseSiteId}/custom”)
public class CustomOccController {

@GetMapping(“/products/{productCode}/compatibility”)
@ResponseBody
public CompatibilityWsDTO checkCompatibility(
@PathVariable String productCode,
@RequestParam String customerProductId) {

CompatibilityData data = customProductFacade
.checkProductCompatibility(productCode, customerProductId);
return dataMapper.map(data, CompatibilityWsDTO.class);
}
}Step 3: Setup Composable Storefront# Install and setup
ng new my-storefront
cd my-storefront
ng add @spartacus/schematics –base-site=electronics –base-url=https://localhost:9002Configure your endpoints:// spartacus-configuration.module.ts
provideConfig({
backend: {
occ: {
baseUrl: environment.occBaseUrl,
prefix: ‘/occ/v2/’,
endpoints: {
product: ‘products/${productCode}?fields=DEFAULT,warrantyInfo’,
productCompatibility: ‘custom/products/${productCode}/compatibility’
}
}
},
context: {
baseSite: [‘electronics’],
currency: [‘USD’],
language: [‘en’]
}
})Step 4: Migrate ComponentsHere’s a real migration example.Old Accelerator JSP:<div class=”product-detail”>
<h1>${product.name}</h1>
<div class=”warranty-info”>
<strong>Warranty:</strong> ${product.warrantyInfo}
</div>
</div>New Angular Component:// custom-product-detail.component.ts
@Component({
selector: ‘app-custom-product-detail’,
templateUrl: ‘./custom-product-detail.component.html’
})
export class CustomProductDetailComponent implements OnInit {
product$: Observable<CustomProduct>;

constructor(
private currentProductService: CurrentProductService,
private customProductService: CustomProductService
) {}

ngOnInit(): void {
this.product$ = this.customProductService.getCustomProduct();
}
}<!– custom-product-detail.component.html –>
<div *ngIf=”product$ | async as product”>
<h1>{{ product.name }}</h1>
<div *ngIf=”product.warrantyInfo”>
<strong>{{ ‘product.warranty’ | cxTranslate }}:</strong>
<p>{{ product.warrantyInfo }}</p>
</div>
</div>Replace default Spartacus components via config:provideConfig({
cmsComponents: {
ProductDetailsTabComponent: {
component: CustomProductDetailComponent
}
}
})Step 5: CheckoutAdding custom checkout steps is straightforward:// Custom step configuration
export const customCheckoutSteps = [
{
id: ‘deliveryAddress’,
name: ‘checkoutProgress.deliveryAddress’,
routeName: ‘checkoutDeliveryAddress’,
type: [CheckoutStepType.DELIVERY_ADDRESS]
},
{
id: ‘giftMessage’, // Your custom step
name: ‘checkoutProgress.giftMessage’,
routeName: ‘checkoutGiftMessage’,
type: [CheckoutStepType.PAYMENT_DETAILS]
},
// … more steps
];Step 6: SSR Setupng add @spartacus/setup –ssrAdd caching for better performance:// server.ts
const cache = new LRU({
max: 100,
ttl: 1000 * 60 * 60 // 1 hour
});

app.engine(‘html’, (filePath, options, callback) => {
const cacheKey = options.req.url;
const cachedHtml = cache.get(cacheKey);

if (cachedHtml) {
return callback(null, cachedHtml);
}

ngExpressEngine({ bootstrap: AppServerModule })(filePath, options, (err, html) => {
if (!err && html) cache.set(cacheKey, html);
callback(err, html);
});
});Step 7: Deploynpm run build:ssrSimple Kubernetes deployment:apiVersion: apps/v1
kind: Deployment
metadata:
name: composable-storefront
spec:
replicas: 3
template:
spec:
containers:
– name: storefront-ssr
image: your-registry/composable-storefront:latest
ports:
– containerPort: 4000
env:
– name: OCC_BASE_URL
value: “https://your-commerce-backend.com”Common Issues & Quick FixesCORS errors?# local.properties
corsfilter.commercewebservices.allowedOrigins=http://localhost:4200Random logouts?provideConfig({
session: { synchronization: true }
})Translations not working? Structure your i18n files properly:// assets/i18n/en/product.json
{
“product”: {
“warranty”: “Warranty”,
“downloadGuide”: “Download Guide”
}
}My AdviceDon’t try to migrate everything at once. Start with one section, test thoroughly, then expand. The Composable Storefront is actively maintained by SAP, so you’re not just modernizing—you’re joining an ecosystem that keeps evolving.The migration is substantial but worth it. Your team gets modern tooling, faster deployments, and better customer experience.ResourcesComposable Storefront DocsOCC API ReferenceSAP CommunityWhat’s been your biggest challenge with this migration? Share in the comments!   Read More Technology Blog Posts by SAP articles 

#SAP

#SAPTechnologyblog

You May Also Like

More From Author