Package Specs
The PackageSpec spec type describes a set of specs to be deployed together as a package. The main element within the PackageSpec is DependencyList which is used to list the catalog items (specs) that should be created or updated prior to adding or updating this catalog item. The DependencyList element holds a list of Dependency child elements. Each Dependency child element refers to a catalog item (spec).
<PackageSpec XMLns="bb_appfx_package" XMLns:common="bb_appfx_commontypes" ID="6AC5B1BE-6266-4F8D-8BFE-3979BA0B6EC0" Name="Widget Package" Description="Used to deploy the widget SDK sample." Author="SDK Author" > <common:DependencyList> <common:Dependency CatalogAssembly="Widget.Catalog.dll" CatalogItem="Widget.Catalog.WidgetCategoryCode.XML"/> <common:Dependency CatalogAssembly="Widget.Catalog.dll" CatalogItem="Widget.Catalog.WidgetDepartmentCode.XML"/> <common:Dependency CatalogAssembly="Widget.Catalog.dll" CatalogItem="Widget.Catalog.WidgetVendorCode.XML"/> <common:Dependency CatalogAssembly="Widget.Catalog.dll" CatalogItem="Widget.Catalog.Widget.Table.XML"/> <common:Dependency CatalogAssembly="Widget.Catalog.dll" CatalogItem="Widget.Catalog.WidgetPart.Table.XML"/> <common:Dependency CatalogAssembly="Widget.Catalog.dll" CatalogItem="Widget.Catalog.WidgetExpense.Table.XML"/> <common:Dependency CatalogAssembly="Widget.Catalog.dll" CatalogItem="Widget.Catalog.WidgetBatch.Table.XML"/> <common:Dependency CatalogAssembly="Widget.Catalog.dll" CatalogItem="Widget.Catalog.WidgetExpenseBatch.Table.XML"/>
Figure: A Sample of the Widget.Package.XML PackageSpec
So what does ‘deployed together as a package’ mean? While the LoadSpec utility is a great way to load and test individual specs into the Infinity database, we need a way to deploy a bunch of specs in a controlled fashion. With Infinity development, a catalog is an assembly (DLL file) that contains embedded catalog items (specs) as resources. We must modify the Build Action property of each spec XML file within our solution to ‘Embedded Resource’. This way, when we compile/build our project, Visual Studio will actually embed our resource (XML spec files) into the compiled assembly (.dll file). An administrator of the application will copy the catalog assemblies that you develop to the Infinity application’s ..\bbappfx\vroot\bin\custom folder. Once the catalog assembly is in its proper place, the administrator can load the assembly using the Catalog Browser. System administrators use the Catalog Browser page to manage the installation of catalog items and new features. Using the Catalog Browser, administrators can determine when they will load new features — promptly after updating, at a later date, or not at all. When an administrator loads your assembly, the Catalog Browser will look inside your assembly and find the PackageSpec. Once located, it will run through the list of Dependency elements within the PackageSpec from the top down. For each Dependency element, it will attempt to load each XML file referenced. The order that we list Dependency elements is important. CodeTableSpecs typically go first, followed by TableSpecs, etc.
Create a Package Spec
To create a Package Spec, select and right-click your Visual Studio project followed by selecting Add\New Item… from the popup menu. You will be prompted to select the appropriate Blackbaud AppFx Catalog item template. Select the Package Spec template and provide a name for the spec file:
Next, you will be presented with a simple wizard that allows you to select the various specs within your project. If you want the wizard to add the dependencies to the Package Spec for you, and thus save you from tedium, select the Create a package spec that includes selected specs from this project radio button followed by selecting the check boxes next to each spec you want added to the Package Spec.
Select OK on the wizard to create the Package Spec:
<PackageSpec xmlns="bb_appfx_package" xmlns:common="bb_appfx_commontypes" ID="b57e39e2-a005-4e70-b17e-8db06d25a3c9" Name="MyPackageSpec Package" Description="REPLACE_WITH_DESCRIPTION" Author="$author$" > <!-- Note: the order of the items listed here is important. For example, you won't be able to load a data form that references a table that hasn't been loaded, etc. In general, the following order is recommended: (functions and procedures first) SQLFunctionSpec SQLStoredProcedureSpec TranslationFunctionSpec (tables next) CodeTableSpec TableSpec (features next) SimpleDataListSpec SearchListSpec RecordOperationSpec DataListSpec (forms next) AddDataFormTemplateSpec EditDataFormTemplateSpec ViewDataFormTemplateSpec (more feature types) BatchTypeSpec BusinessProcessSpec FlashDashSpec IDMapperSpec KpiSpec MergeConfiguration MergeTaskSpec QueryViewSpec ReportSpec SmartFieldSpec SmartQuerySpec (functional areas, pages, and tasks last) PageDefinitionSpec FunctionalAreaSpec TaskSpec --> <common:DependencyList> <common:Dependency CatalogAssembly="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.dll" CatalogItem="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.MajorGiving.Workflow.Package.xml" /> <common:Dependency CatalogAssembly="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.dll" CatalogItem="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.USR_UFN_FUNDRAISERSWORKLOAD.xml" /> <common:Dependency CatalogAssembly="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.dll" CatalogItem="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.MajorGiving.Workflow.EndDateDMConstituencyCodeRecOpUpdate.xml" /> <common:Dependency CatalogAssembly="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.dll" CatalogItem="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.MajorGiving.Workflow.TaskMarkApprove.RecOpUpdate.xml" /> <common:Dependency CatalogAssembly="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.dll" CatalogItem="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.MajorGiving.Workflow.TaskMarkDoNotApprove.RecOpUpdate.xml" /> <common:Dependency CatalogAssembly="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.dll" CatalogItem="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.TestUpdateDMCode.RecOp.xml" /> <common:Dependency CatalogAssembly="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.dll" CatalogItem="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.MajorGiving.Workflow.ResearchRequestSimpleWorkflowAdd.xml" /> <common:Dependency CatalogAssembly="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.dll" CatalogItem="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.MajorGiving.Workflow.SetDataItemValuesAdd.xml" /> <common:Dependency CatalogAssembly="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.dll" CatalogItem="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.MajorGiving.Workflow.TriggerAdd.xml" /> <common:Dependency CatalogAssembly="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.dll" CatalogItem="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.MajorGiving.Workflow.ApprovalPage.GetDataItemValues.ExpressionView.xml" /> <common:Dependency CatalogAssembly="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.dll" CatalogItem="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.MajorGiving.Workflow.ApprovalPage.SummaryView.xml" /> <common:Dependency CatalogAssembly="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.dll" CatalogItem="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.MajorGiving.Workflow.FundraiserSelectProspectPlanView.xml" /> <common:Dependency CatalogAssembly="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.dll" CatalogItem="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.MajorGiving.Workflow.GetCodeTableIDsView.xml" /> <common:Dependency CatalogAssembly="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.dll" CatalogItem="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.MajorGiving.Workflow.ResearchRequestCountView.xml" /> <common:Dependency CatalogAssembly="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.dll" CatalogItem="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.MajorGiving.Workflow.DirSpecialGiving.WorkflowInbox.xml" /> <common:Dependency CatalogAssembly="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.dll" CatalogItem="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.MajorGiving.Workflow.xml" /> <common:Dependency CatalogAssembly="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.dll" CatalogItem="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.MajorGiving.Workflow.ApprovalPage.xml" /> </common:DependencyList> </PackageSpec>
Now that the wizard is done creating the Package Spec, we can arrange our Dependency XML elements in the appropriate order. This is to ensure that foundational specs such as Code Table Specs and Table Specs are loaded into the catalog before the features that depend on the foundational specs. The green comments at the top of the generated Package Spec provide a guide for us to follow when ordering our Dependency XML elements:
<!-- Note: the order of the items listed here is important. For example, you won't be able to load a data form that references a table that hasn't been loaded, etc. In general, the following order is recommended: (functions and procedures first) SQLFunctionSpec SQLStoredProcedureSpec TranslationFunctionSpec (tables next) CodeTableSpec TableSpec (features next) SimpleDataListSpec SearchListSpec RecordOperationSpec DataListSpec (forms next) AddDataFormTemplateSpec EditDataFormTemplateSpec ViewDataFormTemplateSpec (more feature types) BatchTypeSpec BusinessProcessSpec FlashDashSpec IDMapperSpec KpiSpec MergeConfiguration MergeTaskSpec QueryViewSpec ReportSpec SmartFieldSpec SmartQuerySpec (functional areas, pages, and tasks last) PageDefinitionSpec FunctionalAreaSpec TaskSpec -->
Using the comments as a guide, I have re-ordered the Dependency elements:
<common:DependencyList> <!-- SQLFunctionSpec --> <common:Dependency CatalogAssembly="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.dll" CatalogItem="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.USR_UFN_FUNDRAISERSWORKLOAD.xml" /> <!-- RecordOperationSpec --> <common:Dependency CatalogAssembly="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.dll" CatalogItem="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.MajorGiving.Workflow.TaskMarkApprove.RecOpUpdate.xml" /> <common:Dependency CatalogAssembly="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.dll" CatalogItem="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.MajorGiving.Workflow.TaskMarkDoNotApprove.RecOpUpdate.xml" /> <common:Dependency CatalogAssembly="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.dll" CatalogItem="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.MajorGiving.Workflow.EndDateDMConstituencyCodeRecOpUpdate.xml" /> <!-- DataListSpec --> <!-- AddDataFormTemplateSpec --> <common:Dependency CatalogAssembly="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.dll" CatalogItem="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.MajorGiving.Workflow.ResearchRequestSimpleWorkflowAdd.xml" /> <common:Dependency CatalogAssembly="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.dll" CatalogItem="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.MajorGiving.Workflow.SetDataItemValuesAdd.xml" /> <common:Dependency CatalogAssembly="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.dll" CatalogItem="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.MajorGiving.Workflow.TriggerAdd.xml" /> <!-- ViewDataFormTemplateSpec --> <common:Dependency CatalogAssembly="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.dll" CatalogItem="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.MajorGiving.Workflow.ApprovalPage.GetDataItemValues.ExpressionView.xml" /> <common:Dependency CatalogAssembly="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.dll" CatalogItem="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.MajorGiving.Workflow.ApprovalPage.SummaryView.xml" /> <common:Dependency CatalogAssembly="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.dll" CatalogItem="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.MajorGiving.Workflow.FundraiserSelectProspectPlanView.xml" /> <common:Dependency CatalogAssembly="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.dll" CatalogItem="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.MajorGiving.Workflow.ResearchRequestCountView.xml" /> <common:Dependency CatalogAssembly="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.dll" CatalogItem="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.MajorGiving.Workflow.GetCodeTableIDsView.xml" /> <!-- PageDefinitionSpec --> <common:Dependency CatalogAssembly="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.dll" CatalogItem="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.MajorGiving.Workflow.ApprovalPage.xml" /> <!-- Workflow Inbox --> <common:Dependency CatalogAssembly="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.dll" CatalogItem="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.MajorGiving.Workflow.DirSpecialGiving.WorkflowInbox.xml" /> <!-- Workflow --> <common:Dependency CatalogAssembly="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.dll" CatalogItem="Blackbaud.CustomFx.MajorGivingWorkflow.Catalog.MajorGiving.Workflow.xml" /> </common:DependencyList>
Take a Closer Look at the Dependency Element
The CatalogAssembly attribute references the physical assembly file name that is created when you build the Visual Studio project. The value for the CatalogItem attribute should also be prefixed with the Assembly Name. To view the properties for your Catalog project, right click the project within the Microsoft Visual Studio Solution Explorer and select Properties from the popup menu.
Figure: Explore the Dependency element within a PackageSpec