Business Object Data Dictionary
Role of the data dictionary
The data dictionary provides metadata about business objects. BOs are java objects that represent data in a system, often corresponding to a row in a database. In DD terminology, an attribute generally maps to getter/setter methods in the java object, which maps to a field in the database. Technically this is another spring-configuration file so if you are familiar with spring then syntax is pretty self explanatory.
One easy technique to see all available properties in a dictionary definition is open and view the direct and inherited attributes of this class org.kuali.kfs.kns.datadictionary.BusinessObjectEntry
The data dictionary contains information about:
- Descriptive labels for each attribute
- Metadata about each attribute
- How input fields on HTML pages should be rendered for an attribute (e.g. textbox, drop down, etc.)
The data dictionary does not contain information about:
- Which BO does a table correspond to (responsibility of persistence layer, e.g. OJB)
- How fields in the BO correspond to database columns (responsibility of persistence layer, e.g. OJB)
Creating a new Business Object Data Dictionary file
DD file layout
The account DD file has the following format:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:dd="http://rice.kuali.org/dd" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd http://rice.kuali.org/dd http://rice.kuali.org/dd/dd.xsd"> <bean id="Account" parent="Account-parentBean"/> <bean id="Account-parentBean" abstract="true" parent="BusinessObjectEntry"> <property name="businessObjectClass" value="org.kuali.kfs.coa.businessobject.Account"/> <property name="inquiryDefinition" ref="Account-inquiryDefinition"/> <property name="lookupDefinition" ref="Account-lookupDefinition"/> <property name="titleAttribute" value="accountNumber"/> <property name="objectLabel" value="Account"/> <!-- Attribute definition --> <property name="attributes"> <list> <!-- list goes here --> </list> </property> <!-- Collections --> <property name="collections"> <list> <!-- list goes here --> </list> </property> <!-- Relationships --> <property name="relationships"> <list> <!-- list goes here --> </list> </property> <!-- Inactivation blocking definitions --> <property name="inactivationBlockingDefinitions"> <list> <!-- list goes here --> </list> </property> </bean> <bean id="Account-inquiryDefinition" parent="Account-inquiryDefinition-parentBean"/> <!-- Definition goes here --> <bean id="Account-lookupDefinition" parent="Account-lookupDefinition-parentBean"/> <!-- Definition goes here --> </beans>
Typical DD files consist of 4 primary sections (as noted by the commented XML above): inquiry, lookup, attribute, and relationship. Each of these is represented by a comment in the above XML segment and will be discussed in this tutorial.
There are other components in the complete Account DD file, which can be seen in the JavaDoc for the org.kuali.kfs.kns.datadictionary packages.
Inquiry Definition
The inquiry definition indicates which fields are displayed in what order on inquiry screens. Inquiry screens are used to allow users to drill down and find detailed information about a row in the database. Check out the inquiry documentation for a full treatment of how to specify and customize Inquiries using the data dictionary.
Lookup definition
The lookup definition indicates which fields are used to perform a lookup, as well as which fields are listed in the search results. Lookup screens are those that are used to search for a particular row in a table. Check out the lookup documentation for a full treatment of how to declare and customize a lookup for a business object.
Attribute definition
Attributes definition are used to provide metadata about the attributes (i.e. fields) of a business object. Since there are many attributes in the Account
object, only a few attribute definitions are given.
<bean id="Account-chartOfAccountsCode" parent="Account-chartOfAccountsCode-parentBean" /> <bean id="Account-chartOfAccountsCode-parentBean" abstract="true" parent="Chart-chartOfAccountsCode" /> <bean id="Account-chartOfAccounts.codeAndDescription" parent="Account-chartOfAccounts.codeAndDescription-parentBean" /> <bean id="Account-chartOfAccounts.codeAndDescription-parentBean" abstract="true" parent="Chart-codeAndDescription"> <property name="name" value="chartOfAccounts.codeAndDescription" /> <property name="required" value="false" /> <property name="control" > <bean parent="HiddenControlDefinition" /> </property> </bean> <bean id="Account-accountNumber" parent="Account-accountNumber-parentBean" /> <bean id="Account-accountNumber-parentBean" abstract="true" parent="AttributeDefinition"> <property name="name" value="accountNumber" /> <property name="forceUppercase" value="true" /> <property name="label" value="Account Number" /> <property name="shortLabel" value="Account" /> <property name="maxLength" value="7" /> <property name="validationPattern" > <bean parent="AlphaNumericValidationPattern" p:exactLength="7" /> </property> <property name="required" value="true" /> <property name="control" > <bean parent="TextControlDefinition" p:size="10" /> </property> </bean> <bean id="Account-accountName" parent="Account-accountName-parentBean" /> <bean id="Account-accountName-parentBean" abstract="true" parent="AttributeDefinition"> <property name="name" value="accountName" /> <property name="forceUppercase" value="true" /> <property name="label" value="Account Name" /> <property name="shortLabel" value="AcctName" /> <property name="maxLength" value="40" /> <property name="validationPattern" > <bean parent="AnyCharacterValidationPattern" p:allowWhitespace="true" /> </property> <property name="required" value="true" /> <property name="control" > <bean parent="TextControlDefinition" p:size="40" /> </property> </bean>
A bean of type AttributeDefinition
is used to describe metadata for an attribute.
As is common throughout KFS, a field representing the same type of data occurs in many different tables. For example, a chart code may occur in many different tables. In these circumstances, the use of an parent bean reference (parent="Chart-chartOfAccountsCode
) definition allows the reuse of parts of a standard definition from the "master" business object. For example, the chart object would be the "authoritative" source of metadata about the chart of accounts code. Using a parent bean copies metadata about an attribute from "master" BO's attribute but allows overriding of the properties where necessary.
Note that an parent bean relationship does not indicate that there's a foreign key relationship between fields in the BO and the parent attribute's BO. It merely indicates that the metadata between the two fields are shared (or possibly that there is semantic similarity between two attributes). A foreign key relationship is defined either in the persistence layer (e.g. OJB), or using DD-defined relationships (described in the next section).
For the accountNumber attribute, we specify:
- that the account number code should always be uppercased
- what labels should be used when displaying this attribute
- that this field is required during validation (it may not be required on the document, but must be filled in by the user or a pre-rule to be able to be stored to the database)
- that it should be an alphanumeric string with 7 characters with no whitespace or underscores
- that a text field with a max length of 10 should be used to render this attribute when inputting
For the "chartOfAccountsCode" attribute, a parent bean is specified. This reference indicates that all of the metadata for this attribute will come from the Chart
BO's "chartOfAccountsCode" attribute. (As indicated by the standard that an attribute's bean ID be the BO Name-attributeName.)
For the "chartOfAccounts.codeAndDescription" attribute, an attribute reference is specified as well to a Chart
BO attribute. However, instead of copying all of the metadata, this definition overrides a few metadata attributes about the BO attribute.
AttributeReferenceDummy
TODO: Needs Revision - AttributeReferenceDummy should be removed before R3
The AttributeReferenceDummy
DD file has many definitions for generic fields such as yes/no flags, dates, dollar amounts, etc. Using a reference when appropriate simplifies allows for a logical linking of metadata, improves consistency of validation, and simplifies the changing of any metadata for a field, since only the metadata for AttributeReferenceDummy needs to be changed. Check out the AttributeReferenceDummy
DD file for a detailed list of the attributes.
GenericAttributeDefinitions.xml
has many definitions for generic fields such as yes/no flags, dates, dollar amounts, etc. Using one of these beans as the parent when appropriate rather than using AttributeDefinition
simplifies DD files and allows for a logical linking of metadata, improves consistency of validation, and simplifies the changing of any metadata for a field, since only the metadata in GenericAttributeDefinitions.xml
needs to be changed.
All attribute names that appear in any tag in the lookup, inquiry, and other sections should have an attribute defined for them. In particular, nested properties should use an attribute reference so that metadata for the field can be carried over from the nested BO, and selected attribute metadata can be overridden as necessary.
There are other advanced options when defining attributes. Please consult the JavaDoc for more details.
Relationship definition
Foreign key relationships are usually defined within the persistence layer (e.g. OJB) when the relationship can actually be modeled within the DBMS.
Foreign key references often result in a referenced BO being linked to on the main business object. For example, the Account
BO has a field for the chart of accounts code. Because a chart of accounts code uniquely identifies a Chart BO (i.e. it's the primary key), we can also include a Chart attribute on the Account BO as a reference object.
However, there are situations when FK relationships cannot be mapped within the persistence layer because they do not necessarily exist on the database level. The primary example for this is the Person object. Although the base KFS implementation uses the Person details from KIM tables they don't share a direct db relationship. In this case, there is no database-level FK relationship because the data are potentially external to the main KFS database.
Therefore, we need to define relationships within the DD. The following example demonstrates one such mapping.
<property name="relationships" > <list> <bean parent="RelationshipDefinition"> <property name="objectAttributeName" value="accountFiscalOfficerUser" /> <property name="primitiveAttributes" > <list> <bean parent="PrimitiveAttributeDefinition" p:sourceName="accountFiscalOfficerSystemIdentifier" p:targetName="personUniversalIdentifier" /> </list> </property> <property name="supportAttributes" > <list> <bean parent="SupportAttributeDefinition" p:identifier="true" p:sourceName="accountFiscalOfficerUser.personUserIdentifier" p:targetName="personUserIdentifier" /> <bean parent="SupportAttributeDefinition" p:sourceName="accountFiscalOfficerUser.personName" p:targetName="personName" /> </list> </property> </bean> </list> </property> </relationships>
In the above example, the <bean parent="RelationshipDefinition">
tag is describing the keys of the accountFiscalOfficerUser reference object of the Account BO. This attribute is of type UniversalUser (see the java class definition). The primitiveAttributes
property describes the foreign key relationship. In this case, this is saying that the Account's accountFiscalOfficerSystemIdentifierattribute references the personUniversalIdentifier attribute of the reference object, analogous to how it would be defined within a database foreign key. One PrimitiveAttributeDefinition
bean is needed for each field of the pseudo foreign key relationship.
The supportAttributes
property specifies other fields that may be returned from a lookup, but are not foreign key fields. In the above example, when returning a value from a lookup on the accountFiscalOfficerSystemIdentifier attribute of the Account BO (i.e. a nested lookup), not only will the return the UniversalUser's personUniversalIdentifier attribute (i.e. the primary key), the personUserIdentifier and the personName fields will be returned as well.
There are other advanced options when defining relationships. Please consult the JavaDoc for more details.
Kuali documentation is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 2.5 License.
Kuali software is licensed for use pursuant to the Affero General Public License, version 3.
Copyright © 2014 Kuali, Inc. All rights reserved.
Portions of Kuali are copyrighted by other parties as described in the Acknowledgments screen.
Kuali ® is a registered trademark of the Trustees of Indiana University.