SAP Customer Checkout Plugin Development: Working with the CDBSession

Bad CDBSession handling rarely shows up as a clean error. What you get instead are receipts in unexpected states, missing data, or changes that quietly did not persist - and tracing those symptoms back to the actual root cause can take a while. That is why getting the CDBSession right is one of the first things to learn when developing plugins for SAP Customer Checkout.

SAP CCO is architected around its Apache Derby database, and almost every change is directly persisted to it. This approach ensures everything is always properly recorded, even if the POS is shut down or loses power - one of the central requirements for a POS system.

Since SAP CCO follows this architecture, you need to keep this in mind when developing plugins. Every relevant service in SAP CCO uses the CDBSession, so you have surely come across it if you are developing plugins.

Usages of the CDBSession

The CDBSession can either be used directly to execute queries on the database, or it needs to be provided to services you want to use. The latter is the more common case - to get a service instance you normally do the following:

ReceiptChangeNotifierPosService notifierPosService = ServiceFactory.INSTANCE.getOrCreateServiceInstance(
                ReceiptChangeNotifierPosService.class, dbSession);

The service then uses the session internally for all its database operations.

Always close the CDBSession you opened, use try-with-resources, keep it short

How do you get a hold of the CDBSession object? First, the central ground rules:

Creating and using a CDBSession

If you are outside a context where a CDBSession is already available, you create a new one. A common use case is the registration of a ReceiptChangeListener on startup:

try (CDBSession dbSession = CDBSessionFactory.instance.createSession()) {
     ReceiptChangeNotifierPosService notifierPosService = ServiceFactory.INSTANCE.getOrCreateServiceInstance(
             ReceiptChangeNotifierPosService.class, dbSession);
     notifierPosService.registerChangeListener(this);
}

Always try to use try-with-resources. If this is not possible, you have to make sure the session is properly closed after your operation.

Using a CDBSession which is available

There are some PluginExits where a CDBSession is provided (one example being BasePrintJobBuilder.mergeTemplateWithData). If it's available, use it! However: do not close a CDBSession you did not open!

It can also be the case that the current CDBSession is around your PluginExit inside the CCOs core logic, in this case, do not open another one.

Wrap writes in a transaction

If you make any modifications, e.g. to the Receipt, you should use a transaction:

try (CDBSession session = CDBSessionFactory.instance.createSession()) {
    session.beginTransaction();
    // Fetch the receipt from the DB and add the zip code as additional field
    ReceiptPosService receiptPosService = ServiceFactory.INSTANCE.getOrCreateServiceInstance(ReceiptPosService.class, session);
    ReceiptEntity receipt = receiptPosService.getReceipt(receiptId);
    // Add the zip code as additional field
    receipt.addAdditionalField(new AdditionalFieldEntity("ZIP_CODE", "", body.getString("zipCode")));
    session.commitTransaction();
}

For pure reads you can skip the transaction - normally there is nothing to commit or roll back.

A few considerations:

Conclusion

Working with the CDBSession correctly is fundamental to writing reliable SAP CCO plugins. The rules are simple once internalized: reuse a session when one is provided, create your own when it isn't, keep it short-lived, and always close what you opened. Wrap writes in transactions, leave pure reads alone, and prefer try-with-resources whenever possible.

Get these basics right and you avoid a whole category of subtle bugs - leaked sessions, dangling transactions, and inconsistent receipt state - that are painful to debug in a production POS environment.

What's next?

Have you run into tricky CDBSession situations - nested transactions, unclear session ownership in plugin exits, or performance issues? Share your experience in the comments, also if you have questions - I am already thinking of writing another Blog-Post with more advanced examples.

If this was useful, a like or share helps others working on SAP CCO plugins find it too.

ccosapCDBSessionSAPCustomerCheckoutplugin