Skip to end of metadata
Go to start of metadata

Intent

This document outlines the design for the data layer in KRAD targeted for Kuali Rice version 2.4. Within KRAD all persistence and metadata operations should go through the data layer abstraction and not depend on any data store specific logic.

The design goals for the data layer are:

  1. Encapsulate all Rice persistence functionality and metadata into a new krad-data module (part of KRAD modularity)
  2. Provide a simple client API to the KRAD data layer.
  3. Allow data objects to be backed by a variety of data stores and avoid coupling KRAD with any one persistence technology.
  4. Provide a JPA implementation and support for Service-based repositories out of the box
  5. Allow for new data stores to be easily integrated into the framework in the future
  6. Allow for metadata to be combined from multiple sources, including data store metadata, underlying frameworks (such as JPA), and the Data Dictionary

The following items are desired as part of this design, but are possibly out of scope for 2.4. However they should be considered from a design perspective as part of this effort. These are listed in priority order:

  1. Replace the existing External Business Object functionality
  2. Allow for data objects to be validated prior to persistence.
  3. Support for fetch and update of relationships that cross data stores

KRAD Application Architectures

This data layer abstraction will allow for many different storage and retrieval architectures using KRAD. Some possibilities include:

Gliffy Zoom Zoom KRAD Application Architectures

Furthermore, an application can mix persistence strategies to use the optimal architecture for each business case!

Design

The following diagram depicts a high level design of the KRAD Data Layer and how it interacts with some other components of KRAD.

Gliffy Zoom Zoom krad-data-architecture-jpa

For the sake of keeping the interface simple, the data layer will be accessed through a single service named the DataObjectService. To demonstrate the goal of simplification in this effort, this service is intended to replace the following services, classes, and functionality:

  • BusinessObjectService
  • GenericDao
  • CriteriaLookupService
  • BusinessObjectMetadataService
  • DataObjectMetadataService
  • PersistenceService
  • PersistenceStructureService
  • ObjectUtils
  • Methods on ModuleService related to EBOs and EBO metadata

The DataObjectService will be a global service that will provide persistence operations and metadata for all Data Objects available to the application (regardless of which module it is part of). The implementation of this service will then in turn interact through the Data Provider SPI to communicate with the data store and metadata sources that are configured for the data object. Metadata from the data provider will be combined with metadata from the Data Dictionary and/or other sources.

The Data Provider SPI is then made up of two main interfaces, the PersistenceProvider and the MetadataProvider. Implementations of the persistence and metadata providers will need to be created for each supported data store. There will also be built-in implementations of the metadata providers which leverage configuration from the Data Dictionary.

The various providers associated with a data object will be registered with a ProviderRegistry. This can be configured easily through the use of the existing KRAD ModuleConfiguration class. Default providers can be configured for the entire module, along with the ability to associate different providers for a specific data object. For example, the default for a module might be the JPA data provider, but then we may also have a particular data object that we wish to store in MongoDB or load via a remote service.

DataObjectService - The Data Layer API

The DataObjectService has a few main responsibilities:

  1. Provide CRUD persistence operations for data objects.
  2. Provide access to data object metadata.
  3. Create a "wrapper" that can be used to extract property values from a data object instance using the available metadata for that object.
Icon

It is very important to note that the DataObjectService is not intended to be a full-featured or comprehensive abstraction on top of any arbitrary data access technology. The design is intentionally simple and minimal as it is intended to provide a simple interface for CRUD-style operations required in order for the framework to function. Applications can use this service to perform the same operations for their data objects if they wish, but it should not be expected that the service will be able to perform all functions that the native persistence solution (i.e. JPA, JDBC, etc.) can perform. In such cases, application code should utilize the native persistence APIs.

This is in contrast with the KNS BusinessObjectService and PersistenceService, as these services were trying to replicate a mostly complete set of functionality provided by OJB.

It is intended that implementations of DataObjectService will delegate to the appropriate components in the provider SPI for a given data object (see the section on providers below).

DataObjectService  Expand source

Persistence Options

Persistence options can be used to control some optional behavior on save operations. Specific persistence options which each implementation will be required to understand will be:

  • SKIP_LINKING - skips the process of linking attributes on the data object (see more on linking later)

QueryByCriteria

The QueryByCriteria object is part of the criteria API in the Rice core. It is used on remotable services in the middleware modules as well.

If it is desired to use the criteria maps (Map<String, String>) which were common in the KNS framework, then the LookupService can still be used and it will translate the Map<String, String> to QueryByCriteria objects before delegating the call to the DataObjectService.

DataAccessException Translation

The persistence methods on DataObjectService are all declared to throw instances of Spring's org.springframework.dao.DataAccessException. This is part of a framework that Spring provides for translating data access-related exceptions from various formats into a standard exception hierarchy. Providers implemented behind this service will be instructed to try and throw instances of this exception whenever possible.

More information on org.springframework.dao.DataAccessException can be found here:

MetadataRepository

The DataObjectService also provides access to the MetadataRepository. It is intended that this repository will contain metadata about all data objects known to the application. This is in contrast to the old design where there existed both a PersistenceStructureService and DataDictionary which were separate entities.

In this new design, the MetadataRepository is the authoritative and sole source for data object metadata.

It is important to note that the existing concept and classes known as the "DataDictionary" still remain. This data dictionary stores quite a bit more information including user interface configuration. In the new design, the DataDictionary will get it's data object metadata from the MetadataRepository provided by the krad-data module. It can further enhance this metadata by providing additional attributes that don't make sense within the domain of the krad-data module (specifically, things related to the user interface like default controls).

More on the design of the metadata layer can be found later in this document.

DataObjectWrapper

The DataObjectWrapper can be used to fetch properties from the wrapped data object by name, including nested properties (i.e. using "dot-notation"). It actually implements the BeanWrapper interface which is part of the Spring Framework. More on this API can be found here:

In addition to the basic operations provided by the BeanWrapper functionality, this wrapper also provides convenient ways to retrieve or set properties on the data object based on that objects metadata. For example, methods like the following are also available on an instance of a DataObjectWrapper:

  • DataObjectMetadata getMetadata();

  • Object getPropertyValueNullSafe(String propertyName);

  • Map<String, Object> getPrimaryKeyValues();

  • boolean equalsByPrimaryKey(T object);

  • boolean areAllPrimaryKeyAttributesPopulated();

  • boolean areAnyPrimaryKeyAttributesPopulated();

  • List<String> getUnpopulatedPrimaryKeyAttributeNames();

  • etc..

The intent of this class is to help move away from a number of random "utility" methods that were either sitting on static classes like ObjectUtils, or defined on services. Putting them on this wrapper class gives us a succinct API for accessing this kind of information rather than a random assortment of one-off utility methods.

The Provider SPI

In order to allow for different handling of the various operations on the DataObjectService for different data objects, a Service Provider Interface (SPI) is provided for the responsibilities of persistence and metadata loading.

The implementation of DataObjectService should consult a ProviderRegistry to determine how to handle the particular operation which has been requested.

There will be a simple marker interface for providers defined as follows:

All provider interfaces will be placed into the org.kuali.rice.krad.data.provider package.

Persistence Providers

The PersistenceProvider is the part of the SPI for the KRAD data layer which provides the basic CRUD and search operations needed by the KRAD framework. It is intended that there will only ever be a single persistence provider for a given data object. In fact, once a provider for the given data object has been found, it will not continue to search for further matching providers.

The method on PersistenceProvider are identical to the corresponding methods on DataObjectService. Additionally, it should contain a handles method which can be used to determine whether or not the provider handles a specific data object. This is how the DataObjectService implementation will ultimately determine which provider to delegate operations to.

The PersistenceProvider interface will be defined as follows:

 Expand source

Metadata Providers

Icon

Update this section to ensure it is inline with the work that Jonathan did on the embedded MetadataProviders.

The MetadataProvider is the part of the SPI for the KRAD data layer which provides metadata which can be loaded into the MetadataRepository. This provider only has a number of methods that can be defined on it, though the most important is one that allows for it to return metadata for all of the data objects managed by the provider. It is defined as follows:

MetadataProvider  Expand source

 

There may be more than one MetadataProvider which provides metadata for a given data object. In such cases, the order in which providers are evaluated is important as those which are evaluated later in the chain will override any metadata provided by earlier providers. This should be done in such a fashion that metadata is "merged" together into a final representation of a data object as each data object should have only one metadata representation in the data dictionary.

 

Consider the example of a data object defined using JPA as the ORM. In such a case, there would be potentially 3 different providers of metadata which could be combined together and loaded into the data dictionary as through a metadata pipeline as follows:

Gliffy Zoom Zoom krad-metadata-providers

The metadata from the DataDictionary entries will allow for overriding everything from the previous providers. By design, the Data Dictionary becomes the last level of customization to metadata and gives the developer the most control over such customization.

In the scenario of a data object which is represented by a simple "Data Transfer Object" originating from a service, there may be no native provider for metadata. In such cases, the Data Dictionary may be the sole provider of metadata for the data object.

The ProviderRegistry

The provider registry will allow for the various providers implementations to be registered with the system. The implementation of the DataObjectService should delegate to the providers registered therein.

The ProviderRegistry interface is defined as follows:

ProviderRegistry  Expand source

ModuleConfiguration

The KRAD ModuleConfiguration will have properties added for configuring data providers. It will then delegate to the ProviderRegistry to perform registration of those providers. The following methods will be added to ModuleConfiguration in order to support this:

ModuleConfiguration  Expand source

See Providers for examples of configuring modules through XML

Refactoring of Externalizable Business Objects (EBOs)

TODO

Icon

THIS SECTION INCOMPLETE AT THE MOMENT...

Much of the design outlined here will actually allow us to replace the majority of the code in KNS/KRAD related to externalizable business objects, or EBOs. Most of the methods as they exist now are on the ModuleService and have to do with the various basic persistence operations which are modeled by our PersistenceProvider.

As before, a client application would need to load a "module" which loaded the proper providers to access these externally stored business objects. In this case, the custom loading behavior essentially moves from a custom ModuleService into a custom PersistenceProvider.

The metadata for the data object still needs to be loaded into Data Dicationary however.

...

Features

Key and Relationship Linking

JPA (and possibly other data stores) do not provide the automatic linking of relationships and foreign keys like was provided through OJB. Therefore, linking should happen automatically as a result of invoking the save method on the DataObjectService. A PersistenceOption of SKIP_LINKING can be supplied to bypass the linking step.

This linking behavior will do the following:

  • If the primitive foreign key fields for a relationship are present on the parent data object and not set (null), and the related object is non-null, the foreign key fields will be set from the related object
  • If the target of a one to many or many to many relationship has a relationship back to the parent data object that is null, the framework will set the association. In addition, if the target object has primitive foreign key fields back to the parent object that are null these will be set.
  • Related objects which are not read-only (configured to be updated with the parent) will be recursively linked (that is the above two steps will be performed for the relationships of the related object, and so on down the graph

Criteria Queries

Throughout the KRAD framework queries by criteria will be constructed using the Rice Criteria API. The data providers are then responsible for translating the Criteria to an appropriate query structure for the data store (in the case of JPA this will become the JPA QueryByCriteria).

See http://site.kuali.org/rice/2.1.2/apidocs/org/kuali/rice/core/api/criteria/package-summary.html for the Criteria Javadocs.

Service Consolidation

There are many services in KRAD that perform similar operations. These services can be consolidated into our new DataObjectService:

  • BusinessObjectService
  • GenericDao
  • CriteriaLookupService
  • ModuleService - methods related to EBO persistence and metadata
  • BusinessObjectMetadataService
  • DataObjectMetadataService
  • PersistenceService
  • PersistenceStructureService
  • KeyValuesService

Note, however, that we are not planning to remove these classes or methods. Though the majority of them should ultimately end up deprecated. See the section below on "maintaining compatibility" for more information on how this will be handled.

Transaction Management

Currently within KNS/KRAD a JTA transaction is created to wrap each controller method execution. In many cases a JTA transaction is not needed, or an application might not need JTA transaction management at all. Allowing more control over transaction creation will improve performance for applications.

Since controllers are now managed by Spring, we can allow for controller methods to declaratively enable a transaction. This can be done using the @Transactional annotation (as is done for services):

The annotation can be supplied with additional configuration in order to customize the transaction behavior.

The following will also need to be added to the servlet XML:

Any methods that do not have the @Transactional annotation (and if the annotation is not at the controller class level), will not have a wrapping transaction. In these cases transactions may still be created by service methods or other resource local transactions.

In particular, if a PersistenceProvider supports transactions, then it should leverage Spring's transaction management capabilities to participate in an existing transaction if possible, or start a new one otherwise if the particular operation requires a transaction.

Maintaining Compatibility for Legacy KNS and Existing KRAD Code Usage

There are large and established code bases that take advantage of the KNS. There are also a number of applications taking advantage of KRAD since the release of phase 1 of KRAD (2.0.0).

Since this work is being done as part of a minor version of Kuali Rice, efforts need to be made to keep existing code functional upon an upgrade with little to no impact (for example, an upgrade from 2.2.x to 2.3.x should ideally be as much of a drop-in replacement as possible).

This poses a few challenges for this data layer rearchitecture work. Some of the key issues to consider are:

  1. When KRAD was created, it leveraged a large portion of KNS code (after a number of refactorings and repackaging of various classes). This includes services like BusinessObjectService, PersistenceService, PersistenceStructureService, etc. The original KNS code was also refactored to use these new classes rather than a "copy" of the KNS code being made. Essentially, this means that KNS and KRAD share a large portion of infrastructure code, including the entire current persistence and data layer.
  2. Existing applications are going to depend upon the underlying framework to be using OJB. This includes KNS/KRAD-internal mappings such as AdhocRecipients, Notes, Attachments, and DocumentHeader
  3. The current usage of DocumentHeader in KNS/KRAD allows for custom document header mappings as well as ORM-level relationships from application-specific document tables to the KNS/KRAD document table (KRNS_DOC_HDR_T).
  4. As much as possible, we would like for legacy KNS applications to execute nearly identical code to what they did before, and still use OJB under the covers as the persistence technology. This means that legacy KNS applications should not even hit any of the new data architecture.

To help demonstrate this, consider the various entry paths into KNS and KRAD code:

Gliffy Zoom Zoom krad-kns-flow

As we can see from the above, ultimately the KNS and KRAD share a portion of code. However, if we want to do persistence both the old and the new way we need to have some way to detect whether a particular framework should use the legacy or the new data framework.

All of this leads to a need to separate the old and new data architectures entirely. Since there is certain code (like the document framework, lookup framework, and others) which are used by legacy KNS/KRAD apps as well as apps implemented on top of the new data layer, we need a mechanism to determine whether or not a particular code path should use the old or new data layer. We also need a convenient way to manage such decision points within the code.

In order to determine a path forward here, we will break this down into a few different problem spaces:

  1. Persistence Framework
  2. Business Object Classes
  3. Metadata Framework

Before we dig down into each of these there are a couple of global statements that can be made:

  1. Any code in the current "kns" module should be able to remain untouched
  2. The "legacy" portions of the framework that are identified below will be marked as deprecated but will remain in the codebase until Rice 3.0 (or until a decision is made to retire legacy KNS)
  3. In terms of code that needs to be handled, we are primarily concerned about any code which exists with "krad" or one of it's sub modules
  4. There is code outside of KRAD that uses these services which will eventually become legacy (i.e. BusinessObjectService) but since we are providing compatibility for the legacy framework, those can be left alone until they are converted to the new data layer.

Determining whether to call legacy or new data layer

There are a few things we can do to support such a decision:

  1. A configuration parameter will be established called "rice.krad.enableLegacyDataFramework". It should default to false unless the KNSConfigurer is loaded in which case it will be defaulted to true.
    • This will allow for the legacy OJB data framework to be used, even by an application which is only using the new KRAD frontend functionality and no such functionality from the KNS.
  2. On entry into KualiRequestProcessor (the web request entry point for KNS applications) a ThreadLocal will be established indicating the application is in "legacy context".
  3. On entry into PostProcessorService (the workflow entry point for both KRAD and KNS applications), the following will occur:
    1. If the document is a transactional document, check if the document class has a KNS DocumentEntry or the class is not managed by the KRAD MetadataRepository. If so, establish the ThreadLocal indicating the applications is in "legacy context"
    2. If the document is a maintenance document, do the same as above except instead of checking the document class, check the maintainable class.
  4. We will provide a utility class or service that a given class or object can be passed to to determine whether or not that object/class should be handled by the legacy or new data layer. This method will return a boolean indicating whether or not the legacy (OJB) data framework should be used. The logic for that will look as follows:
    • If we are in "legacy context", return true.
    • If legacy data framework is enabled, and the type is loaded into OJB metadata, and the type is not loaded into the KRAD metadata repository then return true.
    • Otherwise return false.

This logic is fairly straightforward and essentially says that if we are in a legacy data context, use the legacy framework. If we are not in a legacy context, check if the legacy framework is enabled and, if so check that the data object has only been configured for use within OJB.

In support of this, we will create a LegacyUtils utility class in KRAD which will contain the following two methods defined as follows:

The implementation of these methods will be according to the algorithm described above.

Additionally, a new singleton service interface will be created named LegacyDataAdapter. This adapter interface will have numerous methods as defined in the next few sections. Code in the krad modules should always call one of these adapters instead of calling the legacy BusinessObjectService, PersistenceService, DataDictionarySerivce, etc. directly. The implementation of these methods will check LegacyUtils to determine whether the legacy or new data layer should be consulted for a particular operation.

Business Object Classes

  • BusinessObject
  • BusinessObjectBase
  • PersistableBusinessObject
  • PersistableBusinessObjectBase
  • ExternalizableBusinessObject
  • TransientBusinessObjectBase

It is intended that all of these classes will become deprecated. The new data layer does not require special interfaces to be on your objects in order for them to be persistable. However, both BusinessObject and PersistableBusinessObject have a number of methods on them related to "refreshing" which need to be dealt with.

This can be handled fairly simply in most cases as follows:

Any code in the krad framework which is calling any of these refresh methods simply needs to check whether or not the object it's been given is an instance of BusinessObject (for the refresh method) or PersistableBusinessObject (for the other methods). If so, simply cast the object and invoke the method. In fact, it's likely that this has already been done in all of the KRAD code.

Persistence Framework Compatibility

The following services in KRAD are currently responsible for functionality related to the persistence layer:

  • BusinessObjectService
  • PersistenceService
  • GenericDao
  • GenericDaoOjb
  • CriteriaLookupService
  • Methods on ModuleService related to EBOs

Some of these classes are simple to deal with and should be handled as follows:

  • GenericDao - deprecate and discontinue use in Rice internal code once transition to JPA is complete
  • GenericDaoOjb - deprecate and discontinue use in Rice internal code once transition to JPA is complete
  • CriteriaLookupService - deprecate and change calling code to use DataObjectService.findMatching instead

For some of these other services, we will need to add some additional corresponding methods to the LegacyDataAdapter. In the implementation of these, these will be delegated to either the legacy services or the new DataObjectService as described below:

Service

Method

If Using Old

If Using New

BusinessObjectService

 

 

 

 

save

BOS.save

DOS.save - with linking disabled

 

linkAndSave

BOS.linkAndSave

DOS.save - with linking enabled

 

findBySinglePrimaryKey

BOS.findBySinglePrimaryKey

DOS.findById

 

findByPrimaryKey

BOS.findByPrimaryKey

DOS.findById

 

delete

BOS.delete

DOS.delete

 

retrieve

BOS.retrieve

DOS.findById - using metadata, extract primary key (id) for given object

 

findMatching

BOS.findMatching

DOS.findMatching - translate Map<String, String> to QueryByCriteria

 

findMatchingOrderBy

don't need it, not used by krad

 

 

findAll

don't need it, not used by krad

 

 

findAllOrderBy

don't need it, not used by krad

 

 

countMatching

don't need it, not used by krad

 

 

getReferenceIfExists

don't need it, only used by legacy dictionary validation service

 

 

manageReadOnly

don't need it, not used by krad

 

 

linkUserFields

don't need it, not used by krad

 

PersistenceService

 

 

 

 

getPrimaryKeyValues

POS.getPrimaryKeyValues

only used by ObjectUtils.equalsByKey - use an as-yet-unamed class (DataObjectUtils?) to use the data dictionary and extract primary key values from a data object given metadata

 

retrieveNonKeyFields

PS.retrieveNonKeyFields

do nothing, no equivalent in new framework

 

retrieveReferenceObject

PS.retrieveReferenceObject

do nothing, no equivalent in new framework

 

retrieveReferenceObjects

don't need it, not used by krad

 

 

resolveProxy

PS.resolveProxy

only used by SerializerServiceBase and XmlObjectSerializerServiceImpl, still need to determine how best to handle serialization and proxies for the new data layer (design is pending)

 

isProxied

PS.isProxied

only used by SerializerServiceBase and XmlObjectSerializerServiceImpl, still need to determine how best to handle serialization and proxies for the new data layer (design is pending)

 

linkObjects

don't need it, not used by krad

 

 

getFlattenedPrimaryKeyFieldValues

don't need it, not used by krad

 

 

allForeignKeyValuesPopulatedForReference

don't need it, only used by legacy dictionary validation service

 

 

refreshAllNonUpdatingReferences

don't need it, only used by PersistableBusinessObjectBase

 

 

isJpaEnabledForKradClass

don't need it, not used

 

 

clearCache

don't need it, not used anywhere

 

The implementation of the LegacyDataAdapter will have the above three legacy services as well as the new DataObjectService injected into it. As per above, it's interface will essentially contain the relevant methods from the aforementioned legacy interfaces.

Metadata Framework Compatibility

The following services in KRAD are currently responsible for functionality related to the metadata layer:

  • PersistenceStructureService
  • DataObjectMetadataService
  • Methods on ModuleService related to EBO metadata

For many of the methods on these services, we will need to add some corresponding methods to the LegacyDataAdapter. In the implementation of these, these will be delegated to either the legacy services or the new MetadataRepository implementation from the krad-data module.

Some notes in terms of maintaining compatibility:

  • An isLockable method should be added to this adapter. If using legacy, invoke PersistenceStructureService.isPersistable. If using new, check if the Versionableinterface is implemented by the data object. MaintainableImpl.isLockable will be modified to delegate to this.
    • MaintenanceDocumentBase.validateBusinessRules should be refactored to use the new isLockable method on the legacy adapter.
  • MaintainbleImpl.getPersistableBusinessObject should be deprecated
  • Refactor MaintenanceDocumentRuleBase.putInactivationBlockingErrorOnPage so that it uses the new legacy adapter where needed

The implementation of the LegacyDataAdapter will have the above legacy services as well as the new MetadataRepository from the krad-data module injected into it.

"Shim" services/daos

KRAD services rely on various "shim" daos which dynamically select a JPA or OJB backend based on a class method argument. In some cases this determination merely selects a statically preconfigured (Spring-wired) DAO implementation. In other cases the DAO implementation is dynamically constructed (in an implementation-specific manner that cannot automatically be generalized) and registered in a static map based on the ModuleConfiguration datasource. In these cases the ModuleConfiguration EntityManager is also dynamically injected into the JPA DAO, and the dataSourceName is injected into the OJB DAO.

Static shims

Shim service

Used by KNS?

Used by non-legacy KRAD?

Needs @Deprecated

Needs @LegacyFramework

JPA DAO dynamic dependencies

OJB DAO dynamic dependencies

Functionality (JPA) can be supplied by DataObjectService?

AttachmentDaoProxy

(tick)

(tick)

(tick)

(tick)

none, statically configured

none, statically configured

Only called in Note.getAttachmentLink, replace with call to additional API in LegacyDataAdapter

DocumentHeaderDaoProxy

(tick)

(tick)

(tick)

(tick)

none, statically configure

non, statically configured

getDocumentHeaderBaseClass - same hardcoded value for both OJB, JPA; getByDocumentHeaderId - called by MaintenanceDocumenteBase.postLoad: replace with LegacyDataAdapter call, called by KNS and KRAD views via DocumentService

MaintenanceDocumentDaoProxy

(tick)

(tick)

(tick)

(tick)

none, statically configured

none, statically configured

storeLocks - called by MaintenanceDocumentBase.postProcessSave: replace with LegacyDataAdapter call, deleteLocks - called by MaintenanceDocumentBase, (KNS and KRAD controllers, DocumentTypeXmlParser) via MaintenanceUtils

NoteDaoProxy

(tick)

(tick)

(tick)

(tick)

none, statically configured

none, statically configured

calls taking Note - move to LegacyDataAdapter; findByremoteObjectId called by DocumentBase, called by various KNS/KRAD

PersistedLookupMetadataDaoProxy

(error)

(error)

(minus)

(minus)

none, statically configured

none, statically configured

called by lookupresultsservice, but this is never called??? - DELETE

SessionDocumentDaoProxy

(error)

(error)

(minus)

(minus)

none, statically configured

none, statically configured

never used? DELETE

PersistenceServiceImpl

(tick)

(error)

(tick)

(tick)

none, statically configured

none, statically configured

(minus) replaced with LegacyDataAdapter

PersistenceStructureServiceImpl

(tick)

(error)

(tick)

(tick)

none, statically configured

none, statically configured

(minus) replaced with LegacyDataAdapter

Dynamic shims

Shim service

Used by KNS?

Used by non-legacy KRAD?

Needs @Deprecated

Needs @LegacyFramework

JPA DAO dynamic dependencies

OJB DAO dynamic dependencies

Functionality (JPA) can be supplied by DataObjectService?

BusinessObjectDaoProxy

(tick)

(error)

(tick)

(tick)

dataSourceName -> entityManager, persistencestructureservice

dataSourceName -> persistencestructureservice

(minus)

DocumentDaoProxy

(tick)

(error)

(tick)

(tick)

dataSourceName -> entityManager, this.documentDaoJpa.getBusinessObjectDao(), this.documentDaoJpa.getDocumentAdHocService()

dataSourceName -> this.documentDaoOjb.getBusinessObjectDao(), this.documentDaoOjb.getDocumentAdHocService(), datasourceName

(question) custom logic to persist document header

LookupDaoProxy

(tick)

(error)

(tick)

(tick)

dataSourceName -> entityManager

dataSourceName -> dataSourceName

(minus)

PersistenceDaoProxy

(tick)

(error)

(tick)

(tick)

just dataSourceName mapping

just dataSourceName mapping

(minus)

CriteriaLookupDaoProxy

(tick)

(error)

(tick)

(tick)

dataSourceName -> entityManager

just dataSourceName

(minus)

Providers

Our initial efforts are focusing just on the data provider for use with JPA. The JPA Data Provider provides persistence and metadata through use of the Java Persistence API and a JPA vendor implementation. Data objects are persisted to a local relational database.

The following page outlines design details for this integration:

Additional Information

  • KRRM-1 - Data cannot be retrieved due to an unexpected error