Broadleaf Microservices
  • v1.0.0-latest-prod

Common Concepts

Background

TMForum provides TMF630 - REST API Design Guidelines as means to provide holistic design patterns that are common across all TMForum REST APIs. This document aims to provide guidance on how Broadleaf has approached these topics and what strategies, assumptions, and opinionated interpretations have been taken in implementing the various TMForum Open APIs. Beyond the concerns outlined in TMF630, this document will also cover any other cross-cutting concepts/patterns that are part of Broadleaf’s TMF strategy.

Security & TMF API Context

Overview

In standard Broadleaf, the APIs normally expect certain proprietary information in order to fulfill a request. For example, we normally expect API consumers to provide a Context Request header that specifies a Broadleaf Catalog ID, a Broadleaf Application ID, a Broadleaf Tenant ID, and so forth. These concepts are important to how data is organized by the system.

However, naturally, TMForum API callers will not know about these proprietary concepts because they are not part of the TMF API specifications. To solve this problem, we have introduced a new concept called a 'TMF API Context'. The TMF API Context concept serves as an intermediary that can provide this proprietary information by default on each request. TMF API consumers are therefore not required to know about Broadleaf’s proprietary concepts and can use the standard TMF API contracts as defined by the OpenAPI specification.

Basically, an admin user can create a new TMF API Context and associate it to proprietary concepts like tenant, catalog, and application. Then, the admin user will assign an Authorized Client to have access to this TMF API Context ID. When the client goes to make API calls, it will prefix the base TMF API URL with the API Context ID. At the time a request comes in, the backend will use that ID to expand the API Context’s details to resolve the Broadleaf tenant, catalog, and application that the request should be performed in.

TMF API Context URL Usage

Setup Guide

  1. In the Broadleaf admin, visit the 'Tenant Management' > 'TMForum API Context' page to manage API Contexts

  2. Create a new API context, specifying details like which catalog, application, and/or sandbox that requests made from this context should operate in. Submit.

  3. After creation, you will also be able to specify additional custom attributes on this API Context.

    • There is a lot of flexibility with what you can do with this, but the main idea is to use this feature to avoid requiring TMF API callers provide custom fields in request payloads to achieve a certain goal.

    • For example, if this API Context will be used to manage ProductStock, you can specify the default Broadleaf Inventory Location that ProductStock should be created in by setting an attribute value for defaultInventoryLocationContextId to the Inventory Location ID. As noted in the TMF 687 implementation documentation, com.broadleafcommerce.tmforum.inventory.tmf687.service.apicontext.InventoryCommonTMFApiContextKeys knows about the attribute key defaultInventoryLocationContextId and will check/use it to process requests.

  4. Once the API Context is established, select and copy the API Context ID from the admin page URL.

  5. Navigate to the 'Security' > 'Authorization Servers' page in the admin and find the Authorized Client that you wish to grant access to this API Context.

  6. In the Authorized Client edit form, under 'Advanced', you will see a 'Custom Attributes' field. Create a new custom attribute called TMF_API_CONTEXTS, and set its value to the API Context ID copied earlier. Save the changes on the client.

    • The end result of this change is that the ClientTMFApiContextTokenEnhancer will read this attribute and populate the TMF_API_CONTEXTS claim on all access tokens issued for this client. When a resource tier service processes a TMF API request, the TMFApiContextHandlerMethodArgumentResolver will verify the requested API Context matches an allowed value in the access token. This is important from a security perspective, as it ensures only clients that have been authorized to use a particular API context can do so.

    • It’s important to note that even after the client is assigned to an API context, they still need to be explicitly assigned the permissions for any endpoints they are trying to access. For example, the client will not have access to the GET ProductOffering endpoint unless they have the TMF_PRODUCT_OFFERING scope and READ_TMF_PRODUCT_OFFERING permission explicitly granted to them. Be sure to assign all relevant scopes/permissions that the client will need for the resources they will manage.

  7. At this point, the admin setup is complete.

    • Any requests made by the AuthorizedClient to TMF APIs should be prefixed with the API Context ID (ex: /{apiContextId}/productCatalogManagement/v5/productOffering)

    • The AuthorizedClient should use the standard OAuth2 flows as normal to obtain access tokens, and then provide them via Authorization headers in each TMF API request

Additional Notes

In each service that contains TMF API endpoints, the TMFApiContextHandlerMethodArgumentResolver engages to resolve the API Context ID that was requested in the URL. This involves making a REST API call to TenantServices to retrieve the API Context. This call is performed with the tmfcoreclient service-to-service AuthorizedClient, which each relevant service is given the authentication details for.

For performance, this API call to retrieve the API Context is cached - please see TMForumCoreCacheAutoConfiguration and TMForumCoreCacheProperties for more details.

Resource id and href Field Values

Support: In compliance with TMF630 version 4.2.0 part 1 section 2.3, the id and href attributes (common to many schemas) will always be returned in responses. Note that href is not a mutable or persisted attribute, but rather a dynamically generated value on reads.

Attribute Selection

TMF630 version 4.2.0 part 1 section 4.3 discusses Query partial Resource representation or attribute selection as the ability to select a subset of the attributes of an entity to be present in the returned representation.

This is useful if you only care about certain fields and don’t want everything in the response.

Per the guidelines:

Attribute selection MUST be enabled on all first level attributes but not on inner classes.

Attribute selection MAY optionally be enabled on all attributes and inner classes.

Selection is based on a fields query parameter of the following form:

GET {apiRoot}/{resourceName}/{resourceID}?fields=\{attributeName*}

TMF APIs typically support this concept on GET requests, but there are cases where POST and PATCH also support this behavior. Furthermore, id, href, and (in the case of v5 APIs) @type fields are required to always be immune to attribute selection and must always be returned.

Support: Broadleaf TMForum APIs currently support attribute selection on all first-level attributes only.

Details: Broadleaf TMForum APIs have introduced a few components and strategies to help facilitate this:

  • AttributeSelectionUtility provides centralized methods for endpoints to quickly parse the fields request parameter and build Jackson SimpleFilterProvider instances that filter out all but those keys in the result

  • JacksonAnnotatingMixinModule provides a way to avoid directly annotating classes with Jackson-specific annotations (such as @JsonFilter) by deferring to a bean-based mixin-applying approach, which is also much more flexible and overridable by clients. This component delegates to JacksonAnnotationMixinMapping beans implemented for each resource class to provide the individualized configuration.

Attribute Filtration

TMF630 version 4.2.0 part 1 section 4.4 discusses Query Resources with attribute filtering as the ability to retrieve resources using an attribute filtering mechanism. This filtering is based on using name-value query parameters on entity attributes of the following form:

GET \{apiRoot} /\{resourceName}?[\{attributeName}=\{attributeValue}&*]

Support: Broadleaf TMForum API’s currently support simple (e.g. fieldName=someValue) equality filters that are AND-ed together (in the case of multiple fields). Each resource supports filtration on different fields based on what the domain can support.

Details: Broadleaf TMForum APIs have introduced a few components to help facilitate this:

  • AttributeFiltersHandlerMethodArgumentResolver: allows endpoint methods to just define an AttributeFilters method parameter which will automatically parse and resolve attribute filtration parameter values based on the resolver provided in a @AttributeFiltersResolution annotation

  • AttributeFiltersRequestResolver: an interface to allow different implementations of resolution logic as needed

  • AbstractAttributeFiltersRequestResolver: serves as a common starting point for resolver implementations that are just based on the field names of a specified entity being filtered. This component allows whitelisting/blacklisting of certain fields as supported/unsupported for filtration.

  • AttributeFiltersRsqlConversionUtility: Responsible for translating the simple equality filters from TMF into RSQL filters, which Broadleaf internally uses when there is a need to specify arbitrary additional filters on a request.

    • Note - often, there will be a RsqlQueryTransformer (or equivalent) implementation registered for each TMF domain to subsequently translate filters from targeting the TMF fields to targeting the BLC-expected fields (particularly if there is a name or type mismatch).

Pagination

TMF630 version 4.2.0 part 1 section 4.5 discusses Query Resources with Iterators as the ability to return large collections in a GET request with pagination. For query based pagination, the following query parameters are used:

  • offset: Requested index for start of resources to be provided in response requested by client

  • limit: Requested number of resources to be provided in response requested by client

Support: Broadleaf TMForum APIs currently support TMForum query-based pagination using offset and limit query parameters. Responses will have the 206 status code as well as an appropriate X-Total-Count/Link response header.

Details: Broadleaf TMForum APIs have introduced a few components to help facilitate this:

  • TMFPageable: an interface and implementation that extends Spring’s default Pageable interface. Represents a Pageable matching the parameters specified for TMF-standard pagination.

    Note
    The default implementation is DefaultTMFPageable. As expected by TMF, this is an offset-based Pageable and therefore does not support page numbering. Despite this, internally, the TMFPageable interface does not extend Broadleaf’s UnnumberedPageable interface. This is because UnnumberedPageable implementations go through special flows during context narrowing which TMFPageable is expected to be excluded from.
  • TMFPageableHandlerMethodArgumentResolver: Allows endpoint methods to just define a TMFPageable method parameter which will automatically be resolved from paging request parameter values, including defaults for unspecified parameters.

Response Headers

At the framework level, Broadleaf supports 'total count' queries only on domains that are not sandbox or catalog discriminated.

If a domain is not sandbox or catalog discriminated, then the paginated response will contain an X-Total-Count header describing the total number of available results. This can be used by the TMF API caller to calculate the next page offset.

If a domain is sandbox or catalog discriminated, then total count will not be available. Typically, such domains are paginated using a proprietary underlyingPageSize concept, because the internal number of results to skip over to get to the next page may not match the 'actual' number of results in the current page. To communicate the appropriate next offset to the API caller, requests for these domains will instead include the TMF-recommended Link header, which will contain a 'next' URI value with pre-filled offset/limit parameters to obtain the next page (if available).

Sorting

TMF630 version 4.2.0 part 1 section 4.7 discusses Sorting as the ability to support a sort directive using query parameters. The following parameters MUST be supported:

  • Sort-Query-Parameters : “sort”, “=”, (Sort-Direction), Sort-Field

  • Sort-Direction : “-“ | “+”

  • Sort-Field: The field to sort on.

Support: Broadleaf TMForum APIs currently support TMForum’s sort directives using query parameters. Each resource supports sorting on different fields based on what the domain can support.

Details: Broadleaf TMForum APIs have introduced a few components to help facilitate this:

  • TMFSortHandlerMethodArgumentResolver an implementation of Spring’s HandlerMethodArgumentResolver and extension of Spring’s default SortHandlerMethodArgumentResolverSupport. This component is used to resolve the TMF-standardized sort parameter syntax. This is internally used by TMFPageableHandlerMethodArgumentResolver during TMFPageable resolution to resolve and set the Sort on the final TMFPageable

    • Note - often, there will be a SortTransformer (or equivalent) implementation registered for each TMF domain to subsequently translate sort requests from targeting the TMF fields to targeting the BLC-expected fields (particularly if there is a name mismatch).

Polymorphic Deserialization

There are certain schemas for which Broadleaf supports out-of-box polymorphic deserialization, where the @type field in an object can drive which specific class the object is resolved to.

CharacteristicValueSpecification

The TMF CharacteristicValueSpecification schema has a wide variety of subtypes, such as StringCharacteristicValueSpecification, BooleanCharacteristicValueSpecification, etc.

The com.broadleafcommerce.tmforum.core.jackson.deserialization.characteristic.PolymorphicCharacteristicValueSpecificationDeserializer is a Jackson JsonDeserializer capable of deserializing an input JSON to the right concrete type.

To achieve this, it delegates to com.broadleafcommerce.tmforum.core.jackson.deserialization.characteristic.CharacteristicValueSpecificationDeserializationHandler beans defined in the Spring context which use either @type or valueType to determine the target type.

Ultimately, the expectation is for mixins (registered via JacksonAnnotationMixinMapping) to invoke this deserializer via @JsonDeserialize if they have a field of type CharacteristicValueSpecification.

ProductOfferingPriceRefOrValue

The TMF ProductOfferingPriceRefOrValue schema can be either a ProductOfferingPrice or a ProductOfferingPriceRef.

The com.broadleafcommerce.tmforum.core.jackson.deserialization.offering.PolymorphicProductOfferingPriceRefOrValueDeserializer is a Jackson JsonDeserializer capable of deserializing an input JSON to the right concrete type.

It will use the @type value from the input to determine the target type.

Ultimately, the expectation is for mixins (registered via JacksonAnnotationMixinMapping) to invoke this deserializer via @JsonDeserialize if they have a field of type ProductOfferingPriceRefOrValue.