级别: 中级 Joe Kubik (jkubik@us.ibm.com), 高级开发人员, IBM Mike Slavin (mslavin@us.ibm.com), 顾问软件工程师, IBM Bill Trautman (btrautma@us.ibm.com), 顾问软件工程师, IBM
2006 年 10 月 12 日
本文将介绍 IBM® WebSphere® Portal V6 中包括的 Content API。本文的目标读者是架构师和系统设计师,这些人员关注构建自定义应用程序,使这些应用程序能够使用库中存储的,并由 Portal Document Manager 管理的文档和其他内容。本文将讨论以下内容:
- 用于管理内容的内容模型
- 应用程序用来与内容模型和包含内容的库进行交互的 API
- API 用来表示模型的结构和编程模型
示例代码演示了如何使用 API。
摘自 IBM WebSphere 开发者技术期刊。
引言
IBM Content Model 和 API 为协作应用程序开发奠定了基础。目前虽然它们不是公共 API 的正式部分,但是已提前由需要构建自定义内容应用程序的人员采用。
围绕面向服务的体系结构 (SOA) 构建的编程模型使应用程序能够通过服务数据对象(Service Data Object,SDO)访问协作内容。
该模型提供了创建、读取、更新和删除 (CRUD) 操作,并且支持其他服务,使应用程序能够管理高级内容管理功能(如版本管理和工作流)。
API 还支持通用持久性模型,以促进应用程序在内容上的协作。WebSphere Portal 在内部将此数据模型用于许多基于内容的应用程序。
文档模型
内容模型的用途是指定内容应用程序共有的元素:
因此,我们引进了内容应用程序的标准模型,该模型可以标准化内容项目(如“文档”和“文件夹”)之间的属性和关系,并定义它们预期的使用模式。
定义模型的部分过程是标准化一组通用元数据属性(如标题、说明和作者等),这些属性是所有内容类型中所通用的。在内容模型中,项目主要由以下三个不同的组构成:基础、元数据和内容。
-
基础类型定义所有其他类型从中扩展的核心类型,并提供内容支持的所有通用属性。
-
元数据类型是特定内容类型与基础类型聚合的类型,提供特定于某类内容的特定属性。元数据类型的属性进一步描述了基本属性集之外的内容状态。这些元数据属性可以包括所有者信息、关于何时发布内容的信息和类别信息等。
-
内容类型是表示并包含“重要”应用程序数据的模型类型。有些内容类型包括:
CollaborativeDocument、Rendition 和 Draft。
图 1 显示了一个 UML 图,它是用于保存文档内容的存储模型的子集。说明了内容、元数据和基础类型之间的属性和关系。
图 1. 文档模型
查看文档模型的大图
表 1 显示了内容模型基于的基础类。
表 1. 作为基础 IBM Content Model 的一部分的基础类
| 类型 | 描述 |
|---|
| Content | 基本内容节点。所有扩展必须是此节点下的子类。 | | Item | 允许版本管理、引用和控制文本搜索的内容节点。 | | Element | 项目必须包含的内容节点。用于构建部分-整体结构。Element 节点不能单独存在,必须存在于某个父项目之下。 | | Component | 允许存储元素的项目类型 | | Collection | 允许使用分层项目结构 | | CompositeComponent | 允许使用分层组件结构 | | CompositeElement | 允许使用分层元素结构 | | Category | 提供分层分类结构 | | DynamicCollection | 提供由查询驱动的内容集合 | | Folder | 存储文档和(子)文件夹的集合 | | DocumentLibrary | 特殊类型的文件夹。封装用于集合中所有内容的功能(如工作流、锁定等) | | Document | 文档存储的特殊绑定项目 | | BinaryElement | 存储简单内容 |
表 2 定义了多个类型使用的结构化属性组。
表 2. 元数据类型
| 类型 | 描述 |
|---|
| MetaData | 所有 MetaData 节点类型的父节点 | | AuditData | 支持跟踪更改。包括谁创建或最后修改文档之类的信息。 | | DynamicData | 支持定义属性的应用程序 | | PeopleData | 提供内容所有者和作者 | | PublishData | 与发布内容相关的元数据。包括文档的有效日期或到期日期之类的信息。 | | CategoryData | 内容类别支持。存放内容所属的类别列表 | | DescriptionData | 描述元数据。包括内容的标题和描述。 | | StandardData | 用于大多数内容的标准元数据。类别、描述、发布、审核和人员元数据的集合 |
表 3 显示了基础内容模型的扩展,以便使用内容库促进协作应用程序的开发。
表 3. 增强的内容类型(基本 IBM Content Model 的扩展)
| 类型 | 描述 |
|---|
| CollaborativeDocument | 提供特定于 Portal Document Manager 的草稿和呈现支持的文档扩展 | | Rendition | 复制转换的协作文档,将其作为特定的模拟类型查看 | | Draft | 文档草稿 | | SearchTemplate | 用户界面视图控制数据。Portal Document Manager 主要使用它保存用于选择要查看的内容的设置 |
服务层体系结构
Content API 体系结构由图 2 所示的几个层组成。这些层可以归类为三个主要方面:服务、传输和中介器。自定义应用程序还可以利用 Binary Property Service。下面详细讨论每个层和组件。
图 2. Content API 服务层
我们将前两层称为高级 服务层和低级 服务层。您使用 Content API 编写的自定义应用程序将主要与这两个层交互。高级服务层目前由 Document Management (DM) Service 和 Library Service 组成。这些服务不与传输层交互,而与低级服务层交互。这两个服务会封装以文档为中心的自定义应用程序可能采用的典型操作。自定义应用程序可以通过直接与较低层服务交互实现与这两个服务提供的相同功能。提供的两个服务可以加快以文档为中心的应用程序的开发工作。
DM Service 提供了特定于 CollaborativeDocument 和 Draft 对象的功能。以文档为中心的应用程序(如 WebSphere Portal Document Management Portlet)可以频繁地使用此服务。DM Service 允许应用程序创建、删除和发布草稿。其中还包含检索 CollaborativeDocument 和 Draft 对象及创建文档库的方法。应用程序可以使用 LibraryService 操作文档库,包括复制、删除和检索库。还可以使应用程序能够操作与库关联的类别。
您可以创建自定义服务层,然后轻松将它们插入到 Content API。
低层服务为:
-
LoginService。在使用 Content API 之前,必须对应用程序进行身份验证,并且从 Content API 检索的结果要基于用户的授权。可以在门户中对库中存储的内容设置各种访问限制,并且 Content API 遵循这些访问权限。如果登录成功,则 LoginService 将 LoginContext 返回到应用程序。大多数的 Content API 调用都要求传入 LoginContext。
-
ContentService。包括对库中内容进行复制、移动、删除、保存和执行文本搜索之类的功能。应用程序还可以使用此服务从库检索单个项目或项目树(图形)。最后,应用程序可以使用此服务锁定和取消锁定库中的内容。
-
VersionService。允许应用程序转换库中的节点,还原转换的节点,向转换的节点添加标签,并检索指定节点的转换历史记录。
-
WorkflowService。内容模型提供了由进程和进程中定义的任务组成的基本工作流功能。WorkflowService 支持应用程序启动和取消工作流进程。应用程序可以使用它来声明、取消声明、检索、审批和完成进程中的任务。
服务层的下面是传输层。当前,Content API 仅支持本地传输层。调用服务层的代码必须驻留在与访问库的后端中介器代码相同的 Java™ 虚拟机中。
体系结构中的最低层是中介器层,它执行对库中数据的访问。中介器层也作为 Service Data Object (SDO) 规范的一部分进行了定义(请参见参考资料)。
中介器层可以接收和返回 SDO 数据图。数据图表示要发送到库或从库检索的数据。将更改保存到库时,中介器先在数据图中处理更改,然后将这些更改发送到库。当检索数据时,中介器会将库中的数据转换为数据图。然后返回数据图并由调用客户机进行处理。
应用程序中与内容库交互的常见用例是显示或直接从 URL 下载内容。如果给定唯一标识符,则 Binary Property Service 可以生成 URL,在调用 URL 时从库检索内容,并响应用户的请求,向用户提供内容流。
DataGraph 详细信息
Content Model 是 SDO v1.0 的 Eclipse Modeling Framework (EMF) http://www.eclipse.org/emf 实现。我们鼓励希望在 Content API 上构建内容模型的开发人员熟悉并掌握这些规范。本文不打算详细解释这些技术。不过,为了讨论 Content Model 实现,有必要简单概述一下。其中,EMF 提供了代码生成工具。给定 UML 模型后,EMF 可以生成作为该模型实现的代码。EMF 生成的代码也是 SDO 实现。首先在 UML 中定义 Content Model,然后使用 EMF 生成 SDO 实现。
SDO 规范是由 IBM、BEA 和其他公司定义的,目的是提供标准化的方法来表示数据,并使应用程序与该数据交互。该规范定义了编程范例和 API。SDO 提供了应用程序与任何对象模型和该对象中包含的数据进行交互的一般方法。可以将任何对象模型看作对象和在每个对象上定义的属性的集合。对象的属性可以是基元类型,也可以是对其他对象的引用。SDO 表示在此抽象级别的数据。
就其核心来看,SDO 可以细分为三个主要组件:
-
DataObject 表示模型中的任何对象。
- 对象的属性由
Property 表示,它可以是基元类型,也可以是对另一个对象的引用。
-
DataGraph 是一组 DataObjects 的容器。
例如,DocumentLibrary 可以包含文件夹,该文件夹进而包含文档。文档具有标题、作者和描述之类的属性。如果应用程序使用 Content API 查询库来获得一组特定的文档,则这些文档会以 DataGraph 的形式返回。DataGraph 将包含满足查询条件的 DataObjects 树或图形。
图 3. 示例 DataGraph
应用程序获得从 Content API 服务调用返回的 DataGraph 后,它就可以根据需要处理数据。可以从 DataGraph 检索数据,并将其显示在应用程序中,或修改 DataGraph 并将其返回到 Content API 服务。
需要指出的一个重要 SDO 范例是在返回要处理的 DataGraph 之前,应用程序可以本地执行对 DataGraph 的所有修改。SDO DataGraph 的职责之一是跟踪对象图形中的任何更改。应用程序可以将新的对象添加到图形中,从图形中删除对象并修改对象的属性。在所有这些更改发生时,DataGraph 将在图形中保持所有更改的摘要。当应用程序完成更改时,DataGraph 被传递回 Content API 服务之一,中介器将处理更改摘要。中介器必须将更改保存到内容库中。
SDO 的强大功能之一是应用程序可以在图形中灵活地访问数据。应用程序可以使用普通的 SDO API 遍历图形,它们可以使用由内容模型定义的对象模型访问数据,或者使用 XPath 从 DataGraph 中提取数据。下面是这些方法的示例。
清单 1. 使用 SDO API:
DataObject draftsFolder = contentService.getTree(...);
DataObject statusReport = (DataObject)draftsFolder.getList("documents").get(1);
String title = statusReport.getString("title");
|
清单 2. 使用 CM 类:
Using the CM Classes:
Folder draftsFolder = (Folder)cs.getTree(...);
Document statusReport = (Document)draftsFolder.getDocuments().get(1);
String title = statusReport.getTitle();
|
清单 3. 使用 XPath:
DataObject draftsFolder = contentService.getTree(...);
DataObject statusReport =
(DataObject)draftsFolder.get("documents[title='Status Report']");
String title = statusReport.getString("title");
|
示例
本部分将介绍创建文档、检索文档、更新某些属性并将这些更改保存在库中的一些示例。这些示例提供了完整的工作样例;但是,它们确实演示了 Content API 编程范例。
清单 4 显示了一些通用步骤,如获取 LoginContext 和对 ContentService 的引用。清单 5 显示了如何在缺省库的根创建文档。清单 6 显示了如何检索刚刚创建的文档,以及如何更新某些属性。
清单 4. 获取 LoginContext
import java.util.Locale;
import com.ibm.content.provider.Provider;
import com.ibm.content.provider.ProviderRegistry;
import com.ibm.content.service.environment.Environment;
import com.ibm.content.service.environment.EnvironmentFactory;
import com.ibm.content.model.dataTypes.LoginContext;
import com.ibm.content.service.LoginService;
import com.ibm.content.service.ContentService;
...
...
// Obtain the default provider from the registry
Provider provider = ProviderRegistry.getInstance().getDefaultProvider();
// Create an environment object using the default locale
Environment env =
EnvironmentFactory.getInstance().createEnvironment(Locale.getDefault(), null);
// Obtain the LoginService from the provider
LoginService loginService =
(LoginService) provider.locateService(LoginService.class.getName());
// Obtain a LoginContext from the LoginService. A reference to a LoginContext is
// needed for all Content API calls.
LoginContext loginContext =
loginService.loginLocal(env, "wpsadmin", "wpsadmin", null, null);
// Obtain a reference to the ContentService
ContentService contentService =
(ContentService) provider.locateService(ContentService.class.getName());
|
清单 5. 创建文档
import java.io.InputStream;
import commonj.sdo.Type;
import commonj.sdo.Property;
import com.ibm.content.model.Folder;
import com.ibm.content.model.Document;
import com.ibm.content.service.Service;
import com.ibm.content.util.TypeRegistry;
import com.ibm.content.model.dataTypes.DataStream;
import com.ibm.content.model.dataTypes.DataStreamFactory;
...
...
// Get a reference to the root folder of the default library
String path = "/contentRoot/icm:libraries";
Folder folder = (Folder) contentService.getItem(loginContext, path, Service.Options.NONE);
// Get the containing property to create the data object in
Property property = folder.getType().getProperty("documents");
// Get the type of the data object
Class typeClass = Document.class;
Type type = TypeRegistry.getInstance().getType(typeClass);
// Start logging changes in the DataGraph
folder.getDataGraph().getChangeSummary().beginLogging();
// Create the Document object
String label = "Status Report.doc";
String title = "Weekly Status Report";
Document doc = (Document) folder.createDataObject(property, type);
doc.setLabel(label);
doc.setTitle(title);
// Create a DataStream for the contents using a file loaded by the ClassLoader
InputStream fileStream = this.getClass().getResourceAsStream("/status-report.doc");
DataStream dataStream =
DataStreamFactory.getInstance().createDataStream(loginContext, fileStream);
doc.setData(dataStream);
// Apply the changes back to the repository
contentService.saveChanges(loginContext, folder.getDataGraph());
|
清单 6. 检索刚刚创建的文档,并更新某些属性
String path = "/contentRoot/icm:libraries/Status Report.doc";
Document doc =
(Document) contentService.getItem(loginContext, path, Service.Options.NONE);
// Start logging changes in the DataGraph
doc.getDataGraph().getChangeSummary().beginLogging();
// Update the title and description
String description = "Weekly status report for week ending 05/19/2006";
doc.setDescription(description);
// Apply the changes back to the repository
contentService.saveChanges(loginContext, doc.getDataGraph());
|
JavaDoc
在 JavaDoc 中提供了介绍编程接口的文档,该文档描述了定义 API 的接口和类。可以在下载部分下载该 Javadoc。
结束语
本文介绍了关于 WebSphere Portal V6.0 中提供的 Content Model 以及与模型一起使用的编程接口的基本知识。本文还提供了 SDO 的简要概述,并讨论了如何将它们与 API 一起使用。还介绍了模型中的重要对象类型,并提供了一些示例代码,展示如何开始使用编程模型。您可以通过可下载的 ZIP 文件获得完整的 Javadoc。通过此信息,您就可以着手利用 Content Model 引入的功能,并学习如何在 WebSphere Portal 6.0 上的自定义应用程序中使用它的工具。
如果您希望继续使用 Content Model 和 API,请与 Greg Melahn (melahn@us.ibm.com) 联系。
下载 | 描述 | 名字 | 大小 | 下载方法 |
|---|
| Content API JavaDoc | contentapi_javadoc.zip | 670KB | HTTP |
|---|
参考资料
作者简介  | 
|  |
Joe Kubik 是 WebSphere Portal 组织中的一名高级开发人员。目前,他重点研究从非浏览器环境(包括桌面应用程序和嵌入式设备)对门户内容的扩展访问。Joe 拥有麻省理工学院的电子工程学学位和仁斯利尔理工大学的计算机科学学位。他在 IBM 任职期间担任多个职位,包括企业硬件和软件开发以及最近的客户机软件开发。Joe 目前在 IBM 的三角研究工业园工作。 |
 | 
|  |
Mike Slavin 在他的事业生涯中一直致力于使用 CORBA、J2EE 和 Web 服务开发分布式应用程序,以及为整个美国客户设计和构建复杂的应用程序。Mike 作为 IT 架构师在 IBM 全球服务部已工作了数年,他最近改为在 IBM 软件部从事 WebSphere Portal 的开发工作。Mike 拥有工程学学位,以优异的成绩毕业于休斯顿大学。Mike 目前在 IBM 的三角研究工业园工作。您可以通过 mslavin@us.ibm.com 与 Mike 联系。 |
 | 
|  |
Bill Trautman 在软件开发方面有 23 年的工作经验。Bill 负责的团队已开发出管理应用程序、用于普及设备的应用程序开发工具和用于服务处理器微码开发的摸似环境。Bill 拥有宾州州立大学工程科学“荣誉学位”。Bill 目前在 IBM 的三角研究工业园工作。您可以通过 btrautma@us.ibm.com 与 Bill 联系。 |
对本文的评价
|