Development
7 min readUnderstanding Broadleaf's core architectural principles is key to building successful extensions. The platform is designed for deep customization, and a grasp of its foundational concepts, from domain separation to data tracking, is essential for any developer looking to extend or integrate with it. This guide covers the fundamental ideas that underpin all Broadleaf domains, providing the groundwork for your custom development.
When building upon a robust, extensible platform like Broadleaf, it’s important to have a strong understanding of the foundational building blocks that the framework provides. Working to master Broadleaf’s extensible domain concepts is a great pace to start! This will allow you to effectively expand upon the out-of-box domain representations and build your own domain that is similarly scoped to a specific tenant, application, or customer context.
A core concept for Broadleaf domain is the separation of concerns between projection and persistence domains. At a high level:
This separation provides crucial flexibility. It ensures that internal implementation details of the database model are not exposed to the outside world, and it allows for a transformed representation of data to be presented to API callers.
Note: In many cases, you may see projection domains by the same name in different services, but each class includes a different set of fields. These are examples of projection domains only deserializing the portions of the JSON payload that they care about.
To handle the transformation between these two representations, Broadleaf uses ModelMapper. This powerful library automates most of the mapping process. Instead of manually writing boilerplate code to copy every field from one object to another, ModelMapper can automatically map fields with the same name and type.
The ModelMapperMappable interface is a Broadleaf-specific contract for this process. Persistence domain classes that implement this interface define two key methods:
When you extend Broadleaf, the platform’s mapping pipeline automatically invokes these methods during typical CRUD (Create, Read, Update, Delete) operations, significantly reducing the amount of code you need to write.
When you extend a Broadleaf class, you need a mechanism to ensure your custom class is used everywhere the base class would be. That’s where TypeFactory comes in. It's a centralized registry that understands the relationship between base Broadleaf types and your custom, extended types.
TypeFactory ensures that:
This component is ubiquitously integrated into the framework, so in most cases, you don’t need to interact with it directly. However, it's important to understand that it's the reason your extensions just work out of the box without requiring you to change any of the core Broadleaf endpoint or object instantiation code.
Note: In rare cases where auto-detection fails, you can explicitly register your custom type using a TypeSupplier bean.
Broadleaf's data tracking facility is a powerful feature that underpins multi-tenancy, sandbox environments, and workflow approvals. It's the system responsible for ensuring that a request only sees the appropriate data for its specific context.
For most extensions, you simply need to ensure your entity is marked with the appropriate trackable interface and tracking configuration; the framework handles the rest of the heavy lifting.
Broadleaf supports Rest Query Language (RSQL), which allows API callers to specify arbitrary filters in a request to limit the results. This is a powerful tool for developers because it minimizes the need to create custom endpoints for every possible query.
An RSQL filter string is passed in the “cq” parameter of a request. The backend parses this string, converts it into JPA criteria, and applies it to the query. This functionality is used extensively in the Broadleaf admin to filter list grids, but it's available in many storefront-focused APIs as well. Instead of writing dozens of hardcoded API endpoints with specific filters, you can expose one RSQL-enabled endpoint and give the caller the power to get exactly the data they need.
A typical CRUD request in Broadleaf follows one of four primary flows, depending on whether the entity is trackable and supports RSQL.
In all of these flows, the fundamental pattern is the same: the REST controller delegates to a service component, which contains the business logic, and the service then delegates to a repository component for persistence or querying. The differences lie in the specific implementations that handle the extra capabilities required for the domain being acted upon.
Mastering these core domain concepts starts your project off on the right foot. For a developer, this means less time fighting boilerplate code and more time building innovative, high-impact features.
By understanding Broadleaf's architectural intent, you can:
Ultimately, these principles empower you to solve complex commerce challenges with elegance and efficiency. For practical examples of these domain extensions, you can check out our repository on GitHub.