Interface TrackableRepository<D extends Trackable>

Type Parameters:
D - The domain type the repository manages
All Superinterfaces:
com.broadleafcommerce.common.extension.DomainTypeAware, com.broadleafcommerce.common.messaging.notification.NotificationStateRepository, org.springframework.data.repository.Repository<D,String>
All Known Subinterfaces:
BaseTrackableRepository<D>, CommonApplicationRepository<D>, CommonCatalogRepository<D>, CommonMarketplaceApplicationCatalogRepository<D>

@NoRepositoryBean public interface TrackableRepository<D extends Trackable> extends org.springframework.data.repository.Repository<D,String>, com.broadleafcommerce.common.messaging.notification.NotificationStateRepository, com.broadleafcommerce.common.extension.DomainTypeAware
Special Spring Data Repository version targeted specifically at maintaining persistence for Trackable domain objects. Actual maintenance of Tracking state during a save operation, including ChangeDetail, SandboxInfo and CatalogInfo information is generally performed by a DefaultTrackableDomainMapperMemberSupport instance prior to passing to the repository.

Fetch behavior may be enhanced by including an additional Narrow annotation to an extending interface that also utilizes the Repository annotation. Narrow annotations take a required NarrowExecutor class argument. The NarrowExecutor is responsible for executing the fetch query defined by the repository query method (or by direct Query definitions through repository specific helper - for example - JpaNarrowingHelper). Furthermore, it is responsible for possibly enhancing the query to perform additional filtering, such as sandbox narrowing and/or catalog filtering.

As a framework, we generaly want to provide the possibility for consumption of repository data by vanilla services that are agnostic to the platform specific nature of a given repository defintion (e.g. a Jpa repository). To achieve this, we generally employ a two-step pattern for setting up a new repository definition in a microservice. First, an interface that extends from TrackableRepository is created. The generics on this interface are kept purposefully general and any general query methods are added here. If specific implementations of a method are required per database platform, an additional interface may be defined and fragment implementation created for each platform. A bean whose id matches the [fragment interface name]Impl pattern should be defined in the platform config (e.g. JpaConfig) to allow the correct fragment implementation to be identified and loaded for execution as part of the Spring Data repository proxy. If overriding existing methods from the TrackableRepository interface, it is important that the overriding method declared in the fragment implementation has a matching signature. for example, to override the save(Trackable, ContextInfo) method implementation, use a concrete method declaration in your fragment implementation similar to this:

 public Trackable save(Trackable catalog, ContextInfo contextInfo) {
     // do something interesting
 }
 

See https://docs.spring.io/spring-data/commons/docs/current/reference/html/#repositories.single-repository-behavior for more information on adding explicit query code behavior to Spring Data repositories.

 @NoRepositoryBean
 public interface ProductRepository<D extends Trackable, I> extends TrackableRepository<D, I> {

    Page<D> findAllByNameContainingIgnoreCase(String query, Pageable page, ContextInfo contextInfo);

 }
 

Next, a platform specific interface is created to reference the database specific definition. An optional Narrow annotation may also be included. This interface is generally empty, unless there is a method to be defined that is truly only possible on a specific platform (e.g. something that can only be done in JpaDB).

 @Repository
 @Narrow(JpaNarrowExecutor.class)
 public interface JpaProductRepository<D extends JpaProduct> extends ProductRepository<D, String> {

 }
 
Service implementations should inject an instance of the general repository interface, and as a result, remain database platform agnostic while using a common interface.

Support for a specific platform repository should be enabled via configuration. For example,

 @Configuration
 @EnableJpaRepositories(
         basePackages = "com.broadleafcommerce.adminnavigation.provider.jpa.repository",
         repositoryFactoryBeanClass = JpaTrackableRepositoryFactoryBean.class)
 @EntityScan(basePackages = "com.broadleafcommerce.menu.provider.jpa.domain")
 @AutoConfigureAfter(JpaDataAutoConfiguration.class)
 public class AdminNavigationJpaAutoConfiguration {}
 
Author:
Jeff Fischer
  • Method Details

    • save

      @Policy(operationTypes={UPDATE,DELETE,CREATE}, param=0) @NonNull D save(@NonNull D entity, @Nullable ContextInfo contextInfo)
      Insert (if not exists) or update the domain instance in the datastore.
      Parameters:
      entity - The Trackable instance
      contextInfo - context information related to multitenancy. Often used to validate visibility and mutability of persistence operations for a catalog.
      Returns:
      The persisted instance
    • saveAll

      @Policy(operationTypes={UPDATE,DELETE,CREATE}, param=0) @NonNull Iterable<D> saveAll(@NonNull Iterable<D> entities, @Nullable ContextInfo contextInfo)
      Insert (if not exists) or update all the domain instances in the datastore. This can end up being a mixture of insert and update operations.
      Parameters:
      entities - The Trackable instances
      contextInfo - context information related to multitenancy. Often used to validate visibility and mutability of persistence operations for a catalog.
      Returns:
      The list of persisted instances
    • findMinSortMember

      @Policy(operationTypes=READ) @Nullable Sortable findMinSortMember(@NonNull Sortable example, @Nullable String minSort, @Nullable ContextInfo contextInfo)
      Given an example member from a sort group, find the first member from that group whose sort value is greater than minSort. If minSort is not specified, then find the first member in the group.

      This can be used to find a member before which to sort the example. In such a case, the minSort value is the sort position of the member after which the example will be sorted. In this case, the reason to get the minSortMember (i.e., the one to sort example before) would be to ensure that example's new sorting value is between minSort and minSortMember's sort value, thereby avoiding collisions.

      Parameters:
      example - The example member of the group used to fashion a query that restricts to the group
      minSort - Results are filtered to be greater than this value
      contextInfo - context information related to multitenancy. Often used to validate visibility and mutability of persistence operations for a catalog.
      Returns:
      The first sorted member based on this fetch
    • findMaxSortMember

      @Policy(operationTypes=READ) @Nullable Sortable findMaxSortMember(@NonNull Sortable example, @Nullable String maxSort, @Nullable ContextInfo contextInfo)
      Given an example member from a sort group, find the first member from that group whose sort value is less than maxSort. If maxSort is not specified, then find the first member in the group.

      This is essentially the complement to findMinSortMember(Sortable, String, ContextInfo). Instead of finding the member before which to sort example using the sorting value of the member after which to sort example, this finds the position-after-member given the sort value of the position-before-member.

      Parameters:
      example - The example member of the group used to fashion a query that restricts to the group
      maxSort - Results are filtered to be less than this value
      contextInfo - context information related to multitenancy. Often used to validate visibility and mutability of persistence operations for a catalog.
      Returns:
      The first sorted member based on this fetch
    • findByContextId

      @Policy(operationTypes=READ) @NonNull Optional<D> findByContextId(@NonNull String contextId, @Nullable ContextInfo contextInfo)
      Retrieve a domain instance based on the context id (see Trackable.getContextId()). If a NarrowExecutor implementation was specified via Narrow, the result should be narrowed based on sandbox and catalog state.
      Parameters:
      contextId - An identifying id
      contextInfo - Request context information around sandbox and multitenant state
      Returns:
      If nothing found, an empty Optional. Otherwise, an Optional containing the narrowed entity.
    • findByContextIdAndCatalog

      @Policy(operationTypes=READ) @NonNull Optional<D> findByContextIdAndCatalog(@NonNull String contextId, @NonNull String catalogId, @Nullable ContextInfo contextInfo)
      Retrieve a domain instance based on the context id (see Trackable.getContextId()). Also restrict the result to a single catalog. This is only useful for catalog discriminated domain types.
      Parameters:
      contextId - An identifying id
      catalogId - The catalog to restrict the result to
      contextInfo - Request context information around sandbox and multitenant state
      Returns:
      If nothing found, an empty Optional. Otherwise, an Optional containing the filtered entity.
    • existsByContextId

      @Policy(operationTypes=READ) boolean existsByContextId(@NonNull String contextId, @Nullable ContextInfo contextInfo)
      Retrieve whether or not an active instance of the item exists for the given context id after any narrowing context is applied.
      Parameters:
      contextId - An identifying id
      contextInfo - Request context information around sandbox and multitenant state
      Returns:
      Whether or not an active instance of the item exists
    • archive

      @Policy(operationTypes=DELETE, param=0) @NonNull D archive(@NonNull D entity, @Nullable ContextInfo contextInfo)
      Archive a record so that it is no longer considered active and is filtered out of results. For production records, this results in the Tracking.getArchived() field being set to True. For sandbox records, both Tracking.getArchived() and SandboxInfo.getArchived() are set to True.
      Parameters:
      entity - The Trackable instance to save as archived
      contextInfo - context information related to multitenancy. Often used to validate visibility and mutability of persistence operations for a catalog.
    • purgeObsoleteSandboxData

      @Policy(operationTypes=DELETE) void purgeObsoleteSandboxData(@NonNull Duration beforeNow)
      Hard-deletes all records which satisfy the following criteria:

      After that, performs an update on all records to prune all ChangeDetails which satisfy the following criteria:

      Parameters:
      beforeNow - duration used to determine whether sandbox data is outdated. The current time minus this duration is the age cutoff that will be used.
    • pruneRestingNotificationStates

      @Deprecated @Policy(operationTypes=UPDATE) void pruneRestingNotificationStates(@NonNull Duration beforeNow)
      Performs an update on all records to prune all NotificationStates from NotificationStateAware.getNotificationStates() which satisfy the following criteria:
      • NotificationState.isAcked() is true or NotificationState.isStopped() is true
      • NotificationState.getChangeTimestamp() is before Instant.now() minus the beforeNow duration
      Parameters:
      beforeNow - NotificationStates whose timestamps are older than the current time minus this duration will be pruned
    • pruneChangeDetails

      @Policy(operationTypes=UPDATE) boolean pruneChangeDetails(@NonNull Object nativeId)
      Updates the entity whose native id matches the given nativeId, setting its Tracking.getChangeDetails() to null.
      Parameters:
      nativeId - the native id of the entity whose change details should be set to null
      Returns:
      true if the update was successful, false otherwise
    • findAll

      @Policy(operationTypes=READ) @NonNull List<D> findAll(@Nullable ContextInfo contextInfo)
      Retrieve all domain instances. If a NarrowExecutor implementation was specified via Narrow, the result should be narrowed based on sandbox and catalog state.
      Parameters:
      contextInfo - Request context information around sandbox and multitenant state
      Returns:
      The list of narrowed entities
    • findAll

      @Policy(operationTypes=READ) @NonNull List<D> findAll(@Nullable ContextInfo contextInfo, @NonNull Class<D> type)
      Retrieve all domain instances. If a NarrowExecutor implementation was specified via Narrow, the result should be narrowed based on sandbox and catalog state.
      Parameters:
      contextInfo - Request context information around sandbox and multitenant state
      type - The results will be limited to the explicit type
      Returns:
      The list of narrowed entities
    • findAllByContextId

      @Policy(operationTypes=READ) @NonNull Iterable<D> findAllByContextId(@NonNull Iterable<String> contextIds, @Nullable ContextInfo contextInfo)
      Retrieve all domain instances based on a list of context ids (see Trackable.getContextId()). If a NarrowExecutor implementation was specified via Narrow, the result should be narrowed based on sandbox and catalog state.
      Parameters:
      contextIds - A list of identifying ids
      contextInfo - Request context information around sandbox and multitenant state
      Returns:
      The list of narrowed entities
    • findAll

      @Policy(operationTypes=READ) @NonNull org.springframework.data.domain.Page<D> findAll(@NonNull org.springframework.data.domain.Pageable pageable, @Nullable ContextInfo contextInfo)
      Retrieve all domain instances, a page at a time. If a NarrowExecutor implementation was specified via Narrow, the result should be narrowed based on sandbox and catalog state.
      Parameters:
      pageable - Information regarding the current page of data to retrieve
      contextInfo - Request context information around sandbox and multitenant state
      Returns:
      The subset (page) of narrowed entities
    • findAll

      @Policy(operationTypes=READ) @NonNull org.springframework.data.domain.Page<D> findAll(@NonNull org.springframework.data.domain.Pageable pageable, @Nullable ContextInfo contextInfo, @NonNull Class<D> type)
      Retrieve all domain instances, a page at a time. If a NarrowExecutor implementation was specified via Narrow, the result should be narrowed based on sandbox and catalog state.
      Parameters:
      pageable - Information regarding the current page of data to retrieve
      contextInfo - Request context information around sandbox and multitenant state
      type - The results will be limited to the explicit type
      Returns:
      The subset (page) of narrowed entities
    • findAll

      @Policy(operationTypes=READ) @NonNull List<D> findAll(@NonNull org.springframework.data.domain.Sort sort, @Nullable ContextInfo contextInfo)
      Retrieve all domain instances using a sort. If a NarrowExecutor implementation was specified via Narrow, the result should be narrowed based on sandbox and catalog state.
      Parameters:
      sort - The sorting information used to define the sort for the query results
      contextInfo - Request context information around sandbox and multitenant state
      Returns:
      The list of narrowed, sorted entities
    • findAll

      @Policy(operationTypes=READ) @NonNull List<D> findAll(@NonNull org.springframework.data.domain.Sort sort, @Nullable ContextInfo contextInfo, @NonNull Class<D> type)
      Retrieve all domain instances using a sort. If a NarrowExecutor implementation was specified via Narrow, the result should be narrowed based on sandbox and catalog state.
      Parameters:
      sort - The sorting information used to define the sort for the query results
      contextInfo - Request context information around sandbox and multitenant state
      type - The results will be limited to the explicit type
      Returns:
      The list of narrowed, sorted entities
    • getEntityInformation

      org.springframework.data.repository.core.EntityInformation<D,String> getEntityInformation()
      Retrieve information about the domain type backing this repository. Generally, the Java type of the backing domain class is the most useful, especially for mapping purposes.
      Returns:
      The backing domain information
    • setTrackableBehaviorUtil

      void setTrackableBehaviorUtil(TrackableBehaviorUtil behaviorUtil)
      Set a utility that is capable of determining the TrackableBehavior state for a domain class.
      Parameters:
      behaviorUtil - A utility that is capable of determining the TrackableBehavior state for a domain class.
    • getTrackableBehaviorUtil

      TrackableBehaviorUtil getTrackableBehaviorUtil()
      Get a utility that is capable of determining the TrackableBehavior state for a domain class.
      Returns:
      A utility that is capable of determining the TrackableBehavior state for a domain class.
    • getDomainType

      default Class<?> getDomainType()
      Specified by:
      getDomainType in interface com.broadleafcommerce.common.extension.DomainTypeAware
    • getTypesToRegisterInMappingContext

      List<Class<?>> getTypesToRegisterInMappingContext()
      Should return the domain type along with all of its extensions that are registered as managed entities. This is useful to inform MappingContext about which persistent entities are available.
      Returns:
      the domain type along with all extensions that are registered as managed entities
    • findByNativeId

      @Policy(operationTypes=READ) @NonNull Optional<D> findByNativeId(@NonNull Object id)
      Finds the entity corresponding to the given native id.
      Parameters:
      id - the native id to find the entity for
      Returns:
      an optional containing the matching entity, Optional.empty() otherwise
    • findPromoteOrientedItems

      default TransitionPackage<D> findPromoteOrientedItems(TargetRelatedRequest request)
      Find items positioned for original and tracking from the perspective of a promotion request. Original should be a less advanced state and target should be a more advanced sandbox state.
      Parameters:
      request - Request that includes properties identifying a sandbox target state
      Returns:
      A package describing the original and target state (if any)
    • findPromotable

      @NonNull default TransitionPackage<D> findPromotable(@NonNull WorkflowPromoteRequest request)
      Retrieve the domain item identified via WorkflowPromoteRequest and also retrieve any domain item existing at the requested target position (if any). The purpose of this call is to establish origin and target in order to advance all or some of the state of the origin object to the state of the target object in the workflow for a promotion.

      Target position is determined by two values in the PromotionRequest: targetSandBoxId, and targetLevel. In most cases, the targetSandBoxId remains the same and the targetLevel increases incrementally beyond TrackingLevel.USER until the final deployment PromotionRequest, which uses a targetLevel of TrackingLevel.PRODUCTION. Different targetSandboxId values can be used to compose isolated sandbox flows. Furthermore, different targetStage values can be used to further inform the system about state in a more complex composed flow.

      Parameters:
      request - container for holding information about the originating domain item and target position for the promotion
      Returns:
      A container for the original and target entities
    • findRebasable

      @NonNull default TransitionPackage<D> findRebasable(@NonNull WorkflowRebaseRequest request)
      Retrieve the domain item identified via WorkflowRebaseRequest and also retrieve any domain item existing at the requested target position (if any). The purpose of this call is to establish origin and target in order to move any missing changes by another author in the target to the original. In this way, the original state is brought up-to-date with the target. If the original contains conflicting changes, the original changes should win.

      Target position is determined by two values in the PromotionRequest: targetSandBoxId, and targetLevel. In most cases, the targetSandBoxId remains the same and the targetLevel increases incrementally beyond TrackingLevel.USER until the final deployment PromotionRequest, which uses a targetLevel of TrackingLevel.PRODUCTION. Different targetSandboxId values can be used to compose isolated sandbox flows. Furthermore, different targetStage values can be used to further inform the system about state in a more complex composed flow.

      Parameters:
      request - container for holding information about the originating domain item and target position for the promotion
      Returns:
      A container for the original and target entities
    • findDeployable

      @NonNull default TransitionPackage<D> findDeployable(@NonNull WorkflowDeployRequest request)
      Retrieve the domain item identified via WorkflowDeployRequest and also retrieve any domain item existing at the requested target position (if any). The purpose of this call is to establish origin and target in order to advance all or some of the state of the origin object to the state of the target object in the workflow for a deployment.

      Target position is determined by two values in the PromotionRequest: targetSandBoxId, and targetLevel. In most cases, the targetSandBoxId remains the same and the targetLevel increases incrementally beyond TrackingLevel.USER until the final deployment PromotionRequest, which uses a targetLevel of TrackingLevel.PRODUCTION. Different targetSandboxId values can be used to compose isolated sandbox flows. Furthermore, different targetStage values can be used to further inform the system about state in a more complex composed flow.

      Parameters:
      request - container for holding information about the originating domain item and target position for the deployment
      Returns:
      A container for the original and target entities
    • findRejectable

      @NonNull default TransitionPackage<D> findRejectable(@NonNull WorkflowRejectRequest request)
      Retrieve the domain item identified via WorkflowRejectRequest and also retrieve any domain item existing at the requested target position (if any). The purpose of this call is to establish origin and target in order to reverse all or some of the state of the origin object to the state of the target object in the workflow for a rejection.

      Target position is determined by two values in the PromotionRequest: targetSandBoxId, and targetLevel. In most cases, the targetSandBoxId remains the same and the targetLevel increases incrementally beyond TrackingLevel.USER until the final deployment PromotionRequest, which uses a targetLevel of TrackingLevel.PRODUCTION. Different targetSandboxId values can be used to compose isolated sandbox flows. Furthermore, different targetStage values can be used to further inform the system about state in a more complex composed flow.

      Parameters:
      request - container for holding information about the originating domain item and target position for the rejection
      Returns:
      A container for the original and target entities
    • findRevertable

      @Nullable default D findRevertable(@NonNull WorkflowRevertRequest request)
      Retrieve the domain item identified via WorkflowRevertRequest. The purpose of this call is to establish origin in order to reverse the state of the origin object.
      Parameters:
      request - container for holding information about the originating domain item
      Returns:
      The repository domain instance to revert
    • findOriginal

      D findOriginal(String contextId, @Nullable String catalogId, @Nullable String applicationId, @Nullable String author, @Nullable String stage, @Nullable String sandboxId, Integer level)
      Given context information, find the original state for the workflow transition operation. Includes promote, deploy, reject and revert operations.
      Parameters:
      contextId - The identifier for the sandboxable item
      catalogId - Any catalog to which the original is related (if any)
      applicationId - Any application to which the original is related (if any)
      author - The author of the entity. Used when the original is a user level sandbox state.
      stage - Additional identifying information
      sandboxId - The sandbox in which the original state exists
      level - The tracking level at which the original state resides
      Returns:
      The originating state for the transition
    • findTarget

      @Nullable D findTarget(String contextId, @Nullable String catalogId, @Nullable String applicationId, @Nullable String author, @Nullable String stage, @Nullable String sandboxId, Integer level, Set<String> visibleFromCatalog)
      Given context information, find the target state (if any) for the workflow transition operation. Includes promote, deploy, reject and revert operations.
      Parameters:
      contextId - The identifier for the sandboxable item
      catalogId - Any catalog to which the target is related (if any)
      applicationId - Any application to which the original is related (if any)
      author - The author of the entity. Used when the target is a user level sandbox state.
      stage - Additional identifying information
      sandboxId - The sandbox in which the target state exists
      level - The tracking level at which the target state resides
      visibleFromCatalog - other catalogs that are visible based on the catalogId
      Returns:
      The target state, or null if no target found