SAP Commerce OCC Deep Dive — Part 6: Designing Secure and Maintainable APIs

Creating an OCC endpoint is usually the easy part. The harder part is understanding what happens from the moment a client sends the request until SAP Commerce returns JSON—and deciding where security, validation, business logic, mapping, response configuration, errors, and performance really belong.


Introduction — Let’s Follow One OCC Request

In Part 5, we built a reusable reorder capability. The business logic no longer belongs to a Storefront Controller.

Storefront
ReorderFacade
ReorderService
├── ReorderValidator
├── ReorderEligibilityStrategy
├── ReorderOrderDao
└── AvailabilityService

Now the business asks:

“Customers should also be able to reorder through our headless storefront.”

So we need an OCC API.

Rather than learning OAuth, Controllers, WsDTOs, field sets, errors, and performance as disconnected topics, we’ll follow one request from the client into SAP Commerce and back out again.

POST /occ/v2/b2bsite/users/current/orders/10001234/reorder
Authorization: Bearer <access-token>
Content-Type: application/json
{
"referenceNumber": "PO-45821"
}

Our successful response will eventually look something like:

{
"orderCode": "10001234",
"status": "SUCCESS",
"cartCode": "00012345"
}

Throughout the flow, I’ll explicitly identify SAP Commerce OOTB APIs and custom illustrative components when they first appear.


1. Start With the URL: What Does /occ/v2 Mean?

Before writing Java, read the endpoint:

/occ/v2/b2bsite/users/current/orders/10001234/reorder

It already tells us several things:

/occ/v2/
├── b2bsite
│ └── BaseSite context
├── users/current
│ └── user context
└── orders/10001234
└── requested resource

OCC v1 vs OCC v2

OCC v1 is the older generation of Commerce REST APIs. OCC v2 is the modern/default OCC generation used by the examples in this article. SAP documents OCC v2 as stateless and more REST-oriented, with required context supplied through the request.

For the 2211 line, OCC v1 is historical. SAP’s current deprecation documentation states that code associated with OCC v1 was removed from the 2211 update stream. SAP also continues to retire the older AddOn-based OCC v2 extension mechanism. That does not mean OCC v2 itself is being removed.

SAP Commerce 2211
└── OCC v2
└── /occ/v2/...

2211 is the SAP Commerce release line. v2 is the OCC API generation. They are different version concepts.

Design Insight

Always ask “v2 of what?” SAP Commerce release version, OCC API generation, and the historical OCC extension mechanism are different concerns.

baseSiteId, current, anonymous, and resource identifiers

b2bsite establishes the BaseSite context. current represents the current authenticated user for applicable OCC endpoints. Other flows may use anonymous.

Cart APIs add another identifier:

/users/{userId}/carts/{cartId}

Depending on the flow, a Cart may be addressed by code, current, or an anonymous Cart GUID.

Because OCC v2 is stateless, don’t design a custom API assuming a browser session will silently carry all required business context between requests.


2. Before Calling OCC, Obtain the Right OAuth Token

Our request contains:

Authorization: Bearer <access-token>

So the client first needs an appropriate OAuth access token.

Application/client token

A client-credentials flow identifies the client application:

curl -X POST \
-d "client_id=my_client" \
-d "client_secret=my_secret" \
-d "grant_type=client_credentials" \
https://localhost:9002/authorizationserver/oauth/token

This answers:

Which application/client is calling?

It does not automatically establish the identity of a particular customer.

User-specific authentication

User-specific OCC operations require authenticated user context. You may encounter older examples that obtain a user token with username/password grant parameters, while newer SAP Commerce/JDK and composable-storefront configurations use authorization-code and PKCE-oriented approaches for public clients.

The production rule is more important than memorizing one curl command:

Choose the OAuth flow according to the client type and the exact SAP Commerce/JDK security configuration.

Do not embed a confidential client_secret in browser JavaScript or a public mobile application.

Design Decision

Choose the OAuth flow from the identity the business operation requires and the type of client making the call. Don’t choose an application token merely because it is easier to obtain when the operation actually depends on a customer’s identity and permissions.

Anonymous customers

Anonymous commerce flows have different identity and Cart-ownership semantics from registered-user flows. The OOTB CommerceWebServicesCartFacade provides web-service-oriented Cart ownership functionality, including current-user and anonymous-Cart checks.

OOTB: OAuth infrastructure and CommerceWebServicesCartFacade.

Common Mistake

Application tokens, user tokens, and anonymous customer context are not interchangeable. They represent different callers and can lead to different authorization decisions.


3. Browser Client? CORS May Be Involved

If the headless storefront runs in a browser on a different origin, the browser may enforce CORS.

https://shop.example.com
CORS
https://api.example.com/occ/v2/...

SAP Commerce Webservices supports CORS configuration for origins, methods, headers, exposed headers, and credentials.

But keep the responsibilities separate:

CORS → May this browser origin call the API?
Authentication → Who is calling?
Authorization → May that caller access this resource?

CORS is not a replacement for OAuth or resource authorization.


4. The Request Enters SAP Commerce: Authentication

Client
│ Authorization: Bearer ...
OAuth / Security
Authenticated Principal

If authentication fails, the reorder business capability should never execute.

If authentication succeeds, we know who the caller is—but we still haven’t proved that this caller may access Order 10001234.


5. Authorization: Can This User Access This Order?

Our request contains:

userId = current
orderCode = 10001234

A valid token doesn’t prove that Order 10001234 belongs to, or is accessible by, the authenticated user.

The same principle applies to:

  • userId,
  • cartId,
  • orderCode,
  • addressId,
  • paymentDetailsId.

A request parameter is input—not proof of ownership.

Design Decision

If access to a resource depends on the current customer or B2B organization, resolve and enforce that authorization from trusted authenticated/business context. Don’t trust a userId or resource code simply because the caller supplied it in the URL.

For B2B implementations, resource authorization may also involve B2B organizational context and the rules that determine which users or units can access a resource.

Common Mistake

“The request has a valid OAuth token” and “the caller may access this Order” are two different statements. Authentication must not replace resource-level authorization.


6. Now the OCC Controller Runs

Only now do we reach our API boundary.

@PostMapping("/{userId}/orders/{orderCode}/reorder")
@ResponseBody
public ReorderWsDTO reorder(
@PathVariable final String userId,
@PathVariable final String orderCode,
@RequestBody final ReorderRequestWsDTO request,
@RequestParam(defaultValue = DEFAULT_FIELD_SET)
final String fields)
{
...
}

The Controller should understand HTTP/API concerns: path/query parameters, request binding, request validation, the authorized API context, the application capability to invoke, response mapping, and HTTP behavior.

It should not become the owner of FlexibleSearch, reorder eligibility, Cart rules, pricing, inventory protocol details, or persistence decisions.


7. JSON Becomes a Request WsDTO

{
"referenceNumber": "PO-45821"
}

At the OCC boundary, that may become a custom request DTO:

public class ReorderRequestWsDTO
{
private String referenceNumber;
// getter / setter
}

Custom: ReorderRequestWsDTO.

Required-field, length, and format checks belong to the request boundary.

JSON
ReorderRequestWsDTO
Request validation
├── invalid → API error
└── valid → continue

But reorder eligibility should not live only in the request validator. A Backoffice action or another caller may invoke the same business capability without an OCC DTO.

Design Insight

The request WsDTO protects the API contract. The business Service protects the business operation.


8. Before Writing Custom Code, Check What SAP Commerce Already Provides

The request is valid. Now the Controller needs to invoke a commerce capability.

Before creating a complete parallel stack, check OOTB APIs.

For example, the OOTB OrderFacade provides Order retrieval/history capabilities such as:

OrderData getOrderDetailsForCode(String code);
SearchPageData<OrderHistoryData>
getPagedOrderHistoryForStatuses(
PageableData pageableData,
OrderStatus... statuses);

OOTB Cart Facades already provide common Cart operations. OCC-specific Cart facade behavior also includes current/anonymous Cart ownership handling.

Our reorder business capability is custom in this scenario, so a custom ReorderFacade/ReorderService can be justified.

Design Decision

Reuse an OOTB Facade or Service when it already represents the capability you need. Introduce a custom capability when the business requirement itself is custom—not merely because the endpoint is custom.

Design Insight

Custom code should represent custom business value. Before creating another Controller → Facade → Service → DAO stack, check whether SAP Commerce already provides the capability or most of it.


9. OCC Controller → Facade → ReorderService

Our Controller can now delegate:

final ReorderData result =
reorderFacade.reorder(
orderCode,
request.getReferenceNumber());
OCC Controller
ReorderFacade
ReorderService

This is where Part 5 pays off.

Below this point, ReorderService doesn’t need to know whether the request came from OCC, Storefront, Backoffice, or another appropriate caller.

Custom: ReorderFacade, ReorderService.


10. Business Validation Runs Below OCC

The Service retrieves the relevant business context and applies the same reorder rules regardless of delivery channel.

ReorderService
ReorderValidator
├── Order status
├── reorder period
├── eligibility
└── entry rules

If the Order isn’t eligible, the business layer should report that business failure. Later in the article we’ll follow that exception back through OCC.

Custom: ReorderValidator, ReorderNotAllowedException.

OOTB examples used by the rule: OrderModel, OrderStatus.


11. Retrieve Data Behind a Persistence Boundary

If the custom reorder operation needs persistence-specific retrieval, keep that concern behind an appropriate DAO/persistence component:

ReorderService
ReorderOrderDao
FlexibleSearchService
Database

OOTB: FlexibleSearchService, FlexibleSearchQuery, SearchResult, OrderModel.

Custom: ReorderOrderDao.

This is where the query-design lessons from Part 3 apply: parameters, result size, Search Restrictions, indexes, and production data volume still matter even though the request started as an OCC API call.


12. External Availability Stays Behind the Integration Boundary

Suppose reorder needs current availability.

ReorderService
AvailabilityService
InventoryAdapter / Client
External Inventory System

Custom illustrative components: AvailabilityService, InventoryAdapter/InventoryClient.

They are not generic OOTB SAP Commerce interfaces.

The business Service asks for availability. The adapter/client owns protocol/provider details such as REST, OData, authentication, payloads, timeouts, and technical errors.

Design Decision

Don’t add Integration Service → Adapter → Client as mandatory layers. Add the boundary that isolates a responsibility that genuinely changes independently. A small integration may need fewer layers; a provider-heavy or protocol-heavy integration may justify more separation.

This is the same integration boundary we established in Part 5; OCC doesn’t change it.


13. Update the Cart Using Existing Commerce Capabilities

Once an entry is eligible and available, don’t manually recreate Cart behavior simply because we’re inside a custom OCC operation.

Reuse OOTB commerce services where appropriate:

final CommerceCartParameter parameter =
new CommerceCartParameter();
parameter.setCart(cart);
parameter.setProduct(product);
parameter.setQuantity(quantity);
parameter.setEnableHooks(true);
final CommerceCartModification modification =
commerceCartService.addToCart(parameter);

OOTB: CommerceCartService, CommerceCartParameter, CommerceCartModification, CartModel.

Design Insight

A custom OCC endpoint doesn’t mean every operation beneath it should also be custom. Reuse platform commerce behavior where it already represents the operation you need.


14. Business Processing Is Complete — Now the Response Travels Back Out

The business capability eventually returns a result:

ReorderService
ReorderResult
ReorderFacade
ReorderData

Notice what it does not return:

ReorderWsDTO

The Service doesn’t need to know OCC exists.

Now we’re moving from business/application representation back toward the external API contract.


15. Why Model → Data → WsDTO?

This is the point where the three representations become useful:

OrderModel
OrderData
OrderWsDTO
JSON

Model

OrderModel is a ServiceLayer/persistence representation.

Data

OrderData is a facade/application representation. OOTB OrderFacade returns Data rather than exposing persistence Models as the external contract.

WsDTO

OrderWsDTO represents the web-service contract.

Design Decision

Use an API-specific representation when the external contract needs to evolve independently from persistence and application structures. Avoid collapsing Model, Data, and WsDTO merely to save mapping code when that would couple the public API to internal change.

SAP describes WsDTO as the OCC REST API data layer, helping decouple the API representation from commerce-services Data objects and enabling dynamic field selection.

Common Mistake

Returning a Model directly from OCC couples the public API to a persistence-oriented representation and makes contract evolution and accidental data exposure harder to control.


16. OOTB DataMapper Creates the WsDTO

SAP Commerce provides the OOTB DataMapper interface in webservicescommons.

final ReorderWsDTO response =
dataMapper.map(
reorderData,
ReorderWsDTO.class,
fields);

Our response path now looks like:

ReorderData
DataMapper
ReorderWsDTO

OOTB: DataMapper, DefaultDataMapper and field-set mapping infrastructure.

Custom: ReorderData, ReorderWsDTO.

Converter/Populator vs DataMapper

A useful mental model is:

  • Converter / Populator: commonly transforms Model/domain representation into Data on the facade/application side.
  • DataMapper: commonly maps Data into WsDTO at the OCC boundary and applies field selection.

That’s a mental model, not a reason to create unnecessary conversion layers.


17. What If We Need a Custom WsDTO Field?

Suppose ReorderData contains:

reorderAllowed

and the API needs the same property.

First check whether standard mapping already handles the matching source/destination property.

For custom mapping behavior, SAP Commerce provides OCC mapping infrastructure including WsDTOMapping for custom converters/mappers/filters related to the WsDTO layer.

The rule is:

Customize the mapping that is different. Don’t replace the whole mapping mechanism because one field is custom.


18. The fields Parameter Decides the Response Shape

Our Controller received:

?fields=DEFAULT

Now we can finally see where that value matters:

ReorderData
DataMapper
├── BASIC
├── DEFAULT
├── FULL
└── explicit fields
ReorderWsDTO

SAP Commerce provides standard OCC field-set concepts such as BASIC, DEFAULT, and FULL, with field-set mapping configuration controlling the properties included at each level.

Consumers can also request explicit fields:

?fields=orderCode,status,cartCode

and field configuration can include nested selections.

A custom mapping could conceptually define:

<entry key="BASIC"
value="orderCode,status"/>
<entry key="DEFAULT"
value="BASIC,cartCode,reorderAllowed"/>
<entry key="FULL"
value="DEFAULT,entries(FULL),warnings"/>

OOTB: field-set infrastructure including FieldSetLevelMapping/FieldSetLevelHelper concepts.

Custom: the actual ReorderWsDTO field definitions.

Design Decision

Put fields required by most consumers in DEFAULT. Keep large, deeply nested, or expensive optional structures out of the default response unless the common use case genuinely requires them. BASIC should stay intentionally small; FULL should be available deliberately, not used automatically.

Design Insight

Return what the consumer needs—not everything the backend knows.


19. The Successful Response Leaves SAP Commerce

After mapping and field filtering:

ReorderWsDTO
JSON serialization
HTTP 200
Client

For example:

{
"orderCode": "10001234",
"status": "SUCCESS",
"cartCode": "00012345"
}

We’ve now followed one successful OCC request from client authentication all the way back to JSON.


20. Run the Same Flow Again — This Time the Business Rule Fails

Now let’s send the same request, but Order 10001234 is no longer eligible for reorder.

Client
Authentication ✓
Authorization ✓
Request validation ✓
OCC Controller
ReorderFacade
ReorderService
ReorderValidator ✗
ReorderNotAllowedException

The Service has done its job: it has expressed a business failure.

But we should not expose a Java exception or stack trace directly to the API consumer.

Translate the failure into the public API contract

SAP Commerce provides common OCC error-handling infrastructure. In current 2211-family APIs, RestExceptionResolver is the relevant common mechanism for mapping exceptions to REST responses; older RestHandlerExceptionResolver APIs are deprecated. OCC also provides ErrorWsDTO representation.

The public response might look like:

{
"errors": [
{
"type": "ReorderNotAllowedError",
"message": "The selected order cannot be reordered.",
"subject": "10001234"
}
]
}

The exact custom error type/fields depend on the contract, but the flow is:

Business Exception
OCC Exception Handling
ErrorWsDTO / stable public error
HTTP 4xx
Client

Don’t leak stack traces, implementation class names, SQL/FlexibleSearch internals, downstream URLs, tokens, or credentials.

Choose HTTP status by meaning

SituationTypical status to consider
Successful operation200 / appropriate success status
Invalid request input400
Missing/invalid authentication401
Authenticated but not authorized403
Resource not found404
Conflict with current resource/business state409 where appropriate
Unexpected server failure500
Temporary service/downstream unavailability503 where appropriate

Design Insight

The business layer decides that the operation failed. The API layer decides how that failure is represented publicly.


21. Run the Flow Again — This Time fields=FULL Is Slow

Now the business operation succeeds, but the client asks for:

?fields=FULL

The Controller still looks clean. Yet the endpoint is slow.

Follow the response path:

fields=FULL
DataMapper
more nested WsDTO fields
more conversion / population
possible queries, calculations, lookups
larger JSON
higher latency

FULL is useful during development, but it isn’t automatically the best production response.

The biggest warning is custom conversion/population code. If a Populator performs FlexibleSearch, pricing calculations, or remote calls, selecting additional response fields can indirectly trigger expensive work.

Common Mistake

Don’t review OCC performance by reading only the Controller. Follow the same end-to-end execution path that the request follows.


22. Collection Variation — Order History Needs Pagination

Our main request dealt with one Order. Now consider:

GET /occ/v2/b2bsite/users/current/orders

Returning every Order for a large customer is not a scalable contract.

The OOTB OrderFacade already provides paged Order history capability:

SearchPageData<OrderHistoryData>
getPagedOrderHistoryForStatuses(
PageableData pageableData,
OrderStatus... statuses);

Pagination affects more than JSON size. It affects the query, memory usage, conversion work, and client navigation.

Design Decision

Choose pagination from expected production cardinality and consumer behavior—not from the small dataset currently visible in development or QA. If the collection can grow, make bounded retrieval part of the API contract early.

Filtering and sorting become data-access concerns

GET /orders?status=COMPLETED&sort=createdDate

Every convenient API filter eventually needs a scalable data-access path.

Consider indexes, allowed fields, authorization, expected data volume, pagination, and query plans before exposing arbitrary filtering/sorting.

This is where Part 6 connects directly back to the FlexibleSearch lessons from Part 3.

Version Note

When implementing custom pagination, check the current 2211 API package rather than copying an old OCC example. Some older pagination types/packages have deprecated replacements.


23. Write Operation Variation — What If the Client Retries?

Our reorder endpoint changes state, so consider this:

Client sends POST
Server performs operation
Network response is lost
Client doesn't know whether it succeeded
Client retries

What should happen?

For some Cart operations, existing Cart/business rules may make duplicate behavior manageable. For payment, order submission, external-system creation, or other retryable commands, duplicate execution can be much more serious.

Don’t add an idempotency framework to every endpoint automatically.

Design Decision

Introduce explicit idempotency when duplicate execution would create a meaningful business risk and retries are realistic. For operations already naturally idempotent or safely deduplicated by existing business semantics, another framework may add complexity without value.

But for every write API ask:

If the same request arrives twice, what is the expected business outcome?


24. Keep Sensitive Data Out of URLs When It Doesn’t Belong There

URLs are commonly captured by infrastructure such as logs, proxies, monitoring tools, browser history, and analytics.

Don’t unnecessarily place sensitive values in:

URL path
query string

Use the request body when the API semantics and security design call for it.

This doesn’t mean every identifier is secret; identifiers such as product codes and Order codes may legitimately be resources in a URL. The point is to avoid treating URLs as a safe place for arbitrary sensitive data.


25. Observability — Follow the Same Request in Production

When this OCC API fails in production, “it returned 500” isn’t enough.

Useful observability may include:

  • request/correlation ID,
  • operation/endpoint,
  • response status,
  • total latency,
  • downstream latency,
  • error category,
  • field level where useful,
  • safe business identifiers where policy permits.

Don’t log access tokens, client secrets, passwords, payment details, or unnecessary personal/sensitive payloads.


26. Test the Flow, Not Just the Happy-Path Controller

An OCC test plan should mirror the execution flow we’ve just followed.

TestWhat it proves
No/invalid tokenAuthentication boundary
Valid customerA token + customerB resourceResource authorization
Invalid request bodyRequest validation
Ineligible OrderBusiness validation + error mapping
BASIC / DEFAULT / FULLField-set contract
Explicit nested fieldsResponse customization
Large Order historyPagination/query behavior
Downstream inventory failureIntegration/error behavior
Retry after timeoutDuplicate/idempotency semantics

SAP Commerce also provides interactive OCC API documentation/Swagger tooling that is useful for exploring contracts and authorized requests, but automated tests should protect the behavior.


27. The Complete Architecture Now Has Meaning

Only now is the full diagram useful, because we’ve followed every stage.

CLIENT
│ /occ/v2/... + Bearer token
CORS (browser, where applicable)
OAuth / Authentication
Authorization / Resource Access
OCC Controller
├── request WsDTO
├── request validation
└── fields
Facade
ReorderService
├── Validator / Strategy
├── DAO → FlexibleSearchService → Database
├── AvailabilityService → Adapter/Client → External System
└── CommerceCartService → Cart
Business Result
Data
DataMapper + Field Sets
WsDTO
JSON / Error Contract
CLIENT

Design Insight

The architecture isn’t valuable because it has many boxes. It’s valuable because each stage has a responsibility that can be understood, tested, reused, and changed without forcing every other stage to change with it.


28. OCC Code Review Checklist

Security and context

  • Which OAuth flow/token type is expected?
  • Is the client public or confidential?
  • Is resource ownership/authorization checked?
  • Are userId, cartId, orderCode, and similar IDs treated as input rather than proof?
  • Is CORS being confused with authorization?
  • Are tokens or secrets logged?

Controller and business boundary

  • Does the Controller focus on API concerns?
  • Is FlexibleSearch or Model persistence happening directly in the Controller?
  • Is business validation reusable below OCC?
  • Could another channel invoke the same business capability?

OOTB reuse

  • Does an OOTB OCC endpoint already provide this?
  • Does an OOTB Facade/Service already provide most of the capability?
  • Are we extending a small gap or copying an entire OOTB flow?

Mapping and fields

  • Are Models kept out of the public contract?
  • Is standard DataMapper sufficient before adding custom mapping?
  • Are BASIC/DEFAULT/FULL intentionally designed?
  • Do Populators/mappers perform expensive work?

Production behavior

  • Are collections paginated?
  • Do filters/sorts have a scalable query path?
  • Is the error contract stable and safe?
  • What happens when a write request is retried?
  • Can the request be traced without logging sensitive data?

29. Scenario Questions

Scenario 1 — Client Token Used for a Customer Resource

A server obtains a client_credentials token and calls an endpoint for customerA’s Order. What establishes that this application may act in that customer context?

Scenario 2 — OCC Controller Calls FlexibleSearch

A Controller retrieves an Order directly with FlexibleSearchService, validates status, and updates the Cart. Which responsibilities have leaked into the API boundary?

Scenario 3 — customerA Requests customerB’s Order

The token is valid, but the Order belongs to another customer. Which stage of our flow should prevent data exposure?

Scenario 4 — BASIC Is Fast, FULL Is Slow

Where would you investigate: Controller, DataMapper, nested field configuration, Populators, query count, external calls, payload size—or all of them?

Scenario 5 — Custom Field Is Missing

The property exists in ReorderData but isn’t in the JSON. Which DataMapper/WsDTO/field-set layers should you inspect before adding more business code?

Scenario 6 — Client Retries After Timeout

The first POST may have succeeded, but the response was lost. What should the business outcome be when the request arrives again?


30. Frequently Asked Questions

Is an application OAuth token the same as a user token?

No. They establish different caller contexts. The exact supported OAuth flows depend on the SAP Commerce/JDK security configuration and client type.

Why does the URL still say /occ/v2 when SAP Commerce is 2211?

Because v2 is the OCC API generation while 2211 is the SAP Commerce release line.

Is OCC v2 being removed because OCC AddOns are deprecated?

No. The older AddOn-based OCC v2 extension mechanism is being retired. OCC v2 itself remains the modern/default OCC API generation in the 2211 documentation.

Why not return OrderModel directly?

Because a persistence Model is not designed to be the public REST contract. Data/WsDTO boundaries provide better control over representation, mapping, field selection, and API evolution.

What is DataMapper?

DataMapper is an OOTB webservicescommons mapping interface used by OCC mapping infrastructure, including property/field filtering.

What are BASIC, DEFAULT, and FULL?

They are standard OCC field-set levels used to control response-field selection. Explicit and nested field configurations can also be requested.

Should a Populator call an external API?

Treat that as a design warning. It can make response construction unexpectedly expensive and couple field selection to remote-system latency.


31. Key Takeaways

  1. Follow the request end to end before deciding where OCC logic belongs.
  2. OCC v2 and SAP Commerce 2211 are different version concepts.
  3. Application tokens, user authentication, and anonymous context are not interchangeable.
  4. Authentication does not replace resource-level authorization.
  5. Keep OCC Controllers focused on the API boundary and reuse the business capability below them.
  6. Check OOTB OCC/Facade/Service capabilities before creating parallel custom implementations.
  7. Keep Model, Data, and WsDTO responsibilities separate.
  8. Use OOTB DataMapper and field-set mechanisms before inventing custom response infrastructure.
  9. Field selection affects not only payload shape but potentially mapping and runtime cost.
  10. Error handling, retries, pagination, observability, and security are part of API design—not afterthoughts.

Final Thoughts

At the beginning of this article, our requirement looked simple:

Expose reorder through OCC.

But following one request showed us that a production OCC API is more than a Controller method.

The request has to establish the right client/user context, pass authentication and authorization, bind and validate its API contract, invoke a reusable business capability, reuse OOTB commerce behavior where appropriate, retrieve/integrate data behind focused boundaries, and then deliberately transform the result into the public response contract.

When something fails, that failure has to travel back through a safe error contract.

When something is slow, we have to follow the response path through field sets, DataMapper, Populators, queries, integrations, and payload construction—not just stare at the Controller.

That’s why I prefer learning OCC by following the request.

The goal isn’t only to know which SAP Commerce class or annotation exists. The goal is to understand why that boundary exists, what SAP Commerce already provides, which alternatives are reasonable, and what should make us choose one design over another.

Once you understand the flow, the individual APIs and annotations make much more sense.

Design Insight

A good OCC API doesn’t expose everything SAP Commerce can do. It exposes a deliberate, secure, maintainable contract over the business capabilities the consumer actually needs.


What’s Coming in Part 7?

SAP Commerce Solr Search Architecture — From Indexed Properties to Production Search Performance

We’ll use the same flow-first approach: start with a real product-search requirement, follow how data moves from SAP Commerce into Solr and back into the storefront/API response, then examine what happens when indexing or query design becomes slow or incorrect.


Technical References

The version-sensitive OCC statements and OOTB API references in this article were checked against SAP Commerce 2211-family SAP Help documentation.


Part of the SAP Commerce Architect Series

Practical SAP Commerce learning focused not only on how the platform works, but on how to think through enterprise design decisions.

Learn. Architect. Build Better.

Leave a comment