Annotation used to describe points of configuration key to establishing a
RoutableDataSource for subsequent inclusion in a
RoutingJpaDataSource defined
elsewhere. When combined with a
DataRouteContext thread local, a RoutingJpaDataSource can
select from one or more injected RoutableDataSource instances that match the routing key
described by DataRouteContext. This allows dynamic connection acquisition and transaction
behavior tied to a specific datasource and backing datastore.
Data route configuration is interesting in cases where it is desirable to run multiple
microservices in a single JVM/classloader. Such a configuration can be advantageous for
development usage, as well as optimized configuration for production. Not every situation
requires every service be deployed in a granular fashion, and infrastructure footprint can be
minimized in some cases by composing multiple services together into a single uber service.
Broadleaf resource tier services are designed to be composed in this way and data route
configuration plays a part in enabling that.
JpaDataRoute is usually described on a JPA specific autoconfiguration for a microservice. For
example,
@ConditionalOnProperty(name = "broadleaf.database.provider", havingValue = "jpa")
@Configuration
@JpaEntityScan(basePackages = "com.broadleafcommerce.promotion.offer.provider.jpa.domain",
routePackage = "com.broadleafcommerce.promotion.offer")
@EnableJpaRepositories(basePackageClasses = JpaOfferRepository.class,
repositoryFactoryBeanClass = JpaTrackableRepositoryFactoryBean.class,
entityManagerFactoryRef = "offerEntityManagerFactory",
transactionManagerRef = "offerTransactionManager")
@EnableConfigurationProperties(OfferProperties.class)
@JpaDataRoute(boundPropertiesType = OfferProperties.class,
routePackage = "com.broadleafcommerce.promotion.offer", routeKey = "offer",
supportingRouteTypes = {NotificationStateDataRouteSupporting.class,
LockDataRouteSupporting.class, ApplicationDataRouteSupporting.class,
TranslationDataRouteSupporting.class})
public class OfferJpaAutoConfiguration {
There are a number of annotations mentioned here, all important in one way or another for
achieving a microservice with full JPA data routing behavior.
@ConditionalOnProperty(name = "broadleaf.database.provider", havingValue = "jpa")
This conditional annotation gates this configuration on whether or not the currently configured
database provider is "jpa" (this is the default). Having such a condition allows for
autoconfiguration against multiple database providers (e.g. jpa and mongo) in the same codebase.
@JpaEntityScan(basePackages = "com.broadleafcommerce.promotion.offer.provider.jpa.domain",
routePackage = "com.broadleafcommerce.promotion.offer")
See
JpaEntityScan for more detail.
@EnableJpaRepositories(basePackageClasses = JpaOfferRepository.class,
repositoryFactoryBeanClass = JpaTrackableRepositoryFactoryBean.class,
entityManagerFactoryRef = "offerEntityManagerFactory",
transactionManagerRef = "offerTransactionManager")
This is the standard Trackable repository declaration, with the exception of explicit declaration
of the entity manager factory ref and the transaction manager ref. Note the "refs" here target
beans resulting from processing of the JpaDataRoute annotation against the
routeKey().
Since the route is predetermined for these repositories, the specific
RoutableDataSource
references can be defined here, rather than leaving the default configuration, which would cause
the components backed by the catch-all
RoutingJpaDataSource to be used. If the latter was
the case, additional
DataRouteContext support would need to be guaranteed, which would be
overkill for these repositories. The counterpoint to this is a repository defined in a common
library whose scope cross-cuts multiple microservice repositories. For example, the
CommonApplicationRepository defined in data tracking core is responsible for looking up
application related data in any supporting datasource. Such a repository should be backed by
RoutingJpaDataSource so that it can service application related data lookup for any
context.
@EnableConfigurationProperties(OfferProperties.class)
See
JpaPropertyRelated for more detail.
@JpaDataRoute(boundPropertiesType = OfferProperties.class,
routePackage = "com.broadleafcommerce.promotion.offer", routeKey = "offer",
supportingRouteTypes = {NotificationStateDataRouteSupporting.class,
LockDataRouteSupporting.class, ApplicationDataRouteSupporting.class,
TranslationDataRouteSupporting.class})
This is the final configuration step for declaring the JPA route for a service. Note, based on
routeKey(), a number of bean declarations are introduced, which can be overridden based
on expected bean ids. See
JpaSpringLiquibaseFactoryBeanRegistrar,
JpaDataRouteEntityManagerFactoryBeanRegistrar,
JpaDataRoutableDataSourceBeanRegistrar,
JpaPackageDataRouteSupplierBeanRegistrar,
JpaEmbeddedDataSourceFactoryBeanRegistrar,
JpaPooledDataSourceFactoryBeanRegistrar,
JpaTransactionManagerFactoryBeanRegistrar,and
JpaTransactionTemplateFactoryBeanRegistrar for more information on the beans resulting
from JpaDataRoute annotation usage.