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/reorderAuthorization: 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 = currentorderCode = 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")@ResponseBodypublic 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
| Situation | Typical status to consider |
|---|---|
| Successful operation | 200 / appropriate success status |
| Invalid request input | 400 |
| Missing/invalid authentication | 401 |
| Authenticated but not authorized | 403 |
| Resource not found | 404 |
| Conflict with current resource/business state | 409 where appropriate |
| Unexpected server failure | 500 |
| Temporary service/downstream unavailability | 503 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 pathquery 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.
| Test | What it proves |
|---|---|
| No/invalid token | Authentication boundary |
| Valid customerA token + customerB resource | Resource authorization |
| Invalid request body | Request validation |
| Ineligible Order | Business validation + error mapping |
| BASIC / DEFAULT / FULL | Field-set contract |
| Explicit nested fields | Response customization |
| Large Order history | Pagination/query behavior |
| Downstream inventory failure | Integration/error behavior |
| Retry after timeout | Duplicate/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
DataMappersufficient 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
- Follow the request end to end before deciding where OCC logic belongs.
- OCC v2 and SAP Commerce 2211 are different version concepts.
- Application tokens, user authentication, and anonymous context are not interchangeable.
- Authentication does not replace resource-level authorization.
- Keep OCC Controllers focused on the API boundary and reuse the business capability below them.
- Check OOTB OCC/Facade/Service capabilities before creating parallel custom implementations.
- Keep Model, Data, and WsDTO responsibilities separate.
- Use OOTB DataMapper and field-set mechanisms before inventing custom response infrastructure.
- Field selection affects not only payload shape but potentially mapping and runtime cost.
- 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.
- SAP Help — Deprecated AddOn-Based OCC V2 Extensions / OCC v1 removal information
- SAP Help — OAuth Client Configuration / PKCE
- SAP Help — OCC Architecture Reference
- SAP Help API — DataMapper
- SAP Help API — webservicescommons.mapping / WsDTOMapping
- SAP Help API — OrderFacade
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