Broadleaf makes significant use of Monetary concepts that involve scale, rounding, serialization, and deserialization. As a result, Broadleaf makes use of the
javax.money.MonetaryAmount interface to assist with these details, which can be inconsistent and complicated when using raw
Number instances such as
Important components to review include:
A high-level interface that defines Money, including Currency and Amount
A high-level interface that defines Currency
A functional interface that returns a
A functional interface that provides a setter for
Specifically, components that require Currency to construct a MonetaryAmount
A collection of utility methods for creating, transforming, and rounding money
A utility to allow for the resolution of preferred currency for a given object
A Jackson extension module that provides components for serializing or deserializing Money
The default system currency is defined by the default Locale of the host operating system. If no default Locale is specified,
USD is used as the default system currency.
Additionally, Broadleaf’s Catalogs and Applications each have a default currency. In certain flows that involve currency (e.g. Catalog and Cart), a component can be invoked to set the default currency for the request. These components implement
com.broadleafcommerce.data.tracking.core.context.ContextInfoCustomizer. For example:
The job of these components is to set the default currency on the
ContextInfo for the current request. These components attempt to resolve the currency based on the current Catalog or Application, depending on the flow. If no currency can be found, then the default system currency is used.
These components can can be overridden to change their behavior, if needed.
ContextInfo#getDefaultCurrency() can be used to determine the default currency for the request. If that value is null,
MonetaryUtils#defaultCurrency() can be used to determine the default system currency.
Additionally, certain objects such as Cart and Product have a currency field on them. If the currency field is populated, then that currency is used for operations that involve that object and its children.
com.broadleafcommerce.data.tracking.core.mapping.money.CurrentCurrencyUtils to resolve the current currency in any situation. The
resolveCurrency method takes in an object and a
ContextInfo. If the object is not null and is a
CurrencySupplier and its currency is not null, then it’s used. Otherwise, if the
ContextInfo is not null and its default currency is not null, then it’s used instead. Finally, if no other currency could be determined then the system currency is used.
With RDBMS (JPA / Hibernate), data is stored in relational database tables. Some of the columns hold JSON data that is serialized and deserialized by Hibernate.
High-level objects such as
Product contain a persistent currency field. If their children are JPA entities and have monetary concerns (i.e.
CartItem) then they contain a
Transient field for currency and amount fields are represented as
BigDecimal. These objects have mutators (getter/setters) for
MonetaryAmount that translates to/from
BigDecimal using the currency on the object. The transient currency is set prior to mapping between the business (projection) domain and the persistent domain. This happens in a
preToMe method, where the currency is determined and set on the child objects.
For JSON representations that are stored in RDBMS fields (e.g.
FulfillmentGroup), they are stored as JSON
MonetaryAmount fields, which means that they contain a serialized amount and currency.
Broadleaf does not currently make use of Solr’s Currency functionality due to the fact that it requires a managed list of currencies and exchange rates. Rather, Broadleaf stores Money in 2 Solr fields defined by the following dynamic fields:
Contains the amount
Contains the currency code
This allows us to uniquely identify each of these necessary pieces of data on a Solr document and construct a
MonetaryAmount instance based on the values.