Sun Java System Content Delivery Server 定制指南
|
|
本章介绍了 Sun Java System Content Delivery Server 事件服务 API。事件服务 API 包含以下外部接口:
- 用于通过数据库客户机应用程序直接查询事件数据的数据库结构
- 可以由 JMS 客户机应用程序订阅的 Java 消息服务 (Java Message Service, JMS) 主题
事件服务将来自事件队列的消息传播到已订阅了事件服务所发布主题的任何相关事件监听器。事件服务还将事件数据存储在 Content Delivery Server 数据库中。可以使用数据库客户机或 JMS 客户机应用程序方法。这两种方法都可以近乎实时地访问相同的信息。
使用事件服务 API 可编写应用程序,以监听特定事件并根据企业需要采取操作。例如,可以使用此 API 编写定制的记帐适配器,以处理购买事件并在购买内容后向订户收费。
图 2-1 简单说明了与事件服务进行交互的通用系统和组件,以图解方式介绍了信息是如何通过各种系统交互进行传递的。
图 2-1 事件服务概述
Content Delivery Server Catalog Manager 和 Vending Manager 组件将相应的消息发布到 JMS 队列中。这些消息由事件服务进行检索和处理。Content Delivery Server 中的任何组件都可以将事件发布到事件服务。由于事件发布是异步操作,因此一旦发送消息,发布消息的组件将继续操作。
事件服务在 Content Delivery Server 环境中作为单独的进程运行。事件服务执行以下任务:
- 使用由各种服务器组件发布的所有消息
- 提取消息的上下文和详细信息,并将该信息插入到数据库中
- 在成功处理消息后向 JMS 队列发送确认
- 出现错误时将消息放入错误队列中
可以随后处理消息,并可能将其重新提交到事件队列中。消息仍确认为由事件服务成功处理。
事件服务 API 的当前实现使用 JMS 点对点 (Point-to-Point, PTP) 消息传送域,从中各种发布程序将消息发布到单个队列,并且事件服务 JMS 客户机应用程序实例将处理这些消息。
事件服务成功处理完事件后,这些事件将被放入数据库中。当事件服务与某个 Vending Manager 一起部署时,这些事件将被放入 Vending Manager 数据库结构中。当事件服务仅与某个 Catalog Manager 一起部署时,这些事件将被放入 Catalog Manager 数据库结构中。有关存储这些消息的数据模型信息,请参见 2.1.1 事件表。
2.1 数据库客户机应用程序
数据驻留在标准关系数据库中,开发者可以通过一组视图以任何能够查询 Oracle 数据库的编程语言编写应用程序。例如,可以使用 Java 编程语言、C++ 或 Visual Basic 编写这些应用程序。
2.1.1 事件表
本节所介绍的表格包含事件服务处理完事件后产生的事件数据。作为集成者,您具有访问这些表格数据的权限。
- 如果将事件服务与某个 Vending Manager 一起部署,请使用用户 prefix_vs_app 连接到 Oracle 数据库。其中 prefix 是为数据库配置文件(用于创建数据库)中 Vending 元素下的 Prefix 元素指定的值。请使用为 Vending 元素下的 Password 元素指定的密码。
- 如果仅将事件服务与某个 Catalog Manager 一起部署,请使用用户 prefix_ps_app 连接到 Oracle 数据库。其中 prefix 是为数据库配置文件(用于创建数据库)中 Catalog 元素下的 Prefix 元素指定的值。请使用为 Catalog 元素下的 Password 元素指定的密码。
有关数据库配置文件的信息,请参见《Sun Java System Content Delivery Server 5.1 安装指南》。
2.1.1.1 CDS_EVENT 表
CDS_EVENT 表包含事件服务成功处理的每个事件的记录。处理事件时,此表将实时更新。
表 2-1 CDS_EVENT 表
列名
|
数据类型
|
描述
|
CDS_EVENT_ID
|
NUMBER(18)
|
系统生成的用作记录 ID 的唯一数字。此字段是表的主键。
|
CDS_EVENT_DATE
|
DATE
|
表示事件消息生成时间的时间戳。
|
CDS_EVENT_TYPE_ID
|
NUMBER(18)
|
CDS_EVENT_TYPE 表的外键。
|
EVENT_SOURCE_ID
|
NUMBER(18)
|
EVENT_SOURCE_TYPE 表的外键。
|
SVR_INSTANCE_ID
|
NUMBER(18)
|
系统数据。
|
SVR_SESSION_ID
|
VARCHAR2(128)
|
系统数据。
|
SUB_SYSTEM_ID
|
VARCHAR2(80)
|
与会话及事件关联的 MSISDN。如果 MSISDN 未知,则该列为 Null。
|
CDS_USER_ID
|
NUMBER(18)
|
与会话及事件关联的 Content Delivery Server 用户 ID。如果用户未登录,则此列可能为 Null。
|
VENDOR_ID
|
NUMBER(18)
|
内容提供商 ID。
|
CONTENT_ID
|
NUMBER(18)
|
内容表的外键。
|
RAW_EVENT_MESSAGE
|
CLOB
|
原始事件消息 XML。
|
CREATE_DATE
|
DATE
|
系统数据。
|
MOD_DATE
|
DATE
|
系统数据。
|
LOCK_VERSION
|
NUMBER(1)
|
系统数据。
|
2.1.1.2 CDS_EVENT_TYPE 表
CDS_EVENT_TYPE 表是一个包含事件类型定义的静态表。在 2.3 事件和事件数据中列出了这些定义。
表 2-2 CDS_EVENT_TYPE 表
列名
|
数据类型
|
描述
|
CDS_EVENT_TYPE_ID
|
NUMBER(18)
|
系统生成的用作记录 ID 的唯一数字。此字段是表的主键。
|
CDS_EVENT_GROUP_ID
|
NUMBER(18)
|
EVENT_GROUP 表的外键。用于对事件类型进行分组。
|
CDS_EVENT_TYPE_NAME
|
VARCHAR2(80)
|
可读名称。
|
DESCRIPTION
|
VARCHAR2(80)
|
特定事件类型的描述。
|
LONG_DESCRIPTION
|
VARCHAR2(255)
|
事件类型的详细描述(如果需要)。
|
IS_ACTIVE
|
NUMBER(1)
|
表示是否为活动事件类型的标志。
|
CREATE_DATE
|
DATE
|
系统数据。
|
MOD_DATE
|
DATE
|
系统数据。
|
LOCK_VERSION
|
NUMBER(1)
|
系统数据。
|
2.1.1.3 EVENT_SOURCE_TYPE_ID 表
EVENT_SOURCE_TYPE_ID 表是一个包含事件源类型定义的静态表。
表 2-3 EVENT_SOURCE_TYPE_ID 表
列名
|
数据类型
|
描述
|
EVENT_SOURCE_TYPE_ID
|
NUMBER(18)
|
系统生成的用作记录 ID 的唯一数字。此字段是表的主键。
|
EVENT_SOURCE_TITLE
|
VARCHAR2(255)
|
可读名称。
|
CREATE_DATE
|
DATE
|
系统数据。
|
MOD_DATE
|
DATE
|
系统数据。
|
LOCK_VERSION
|
NUMBER(1)
|
系统数据。
|
2.1.2 报告工具
可以使用任何连接到 Oracle 数据库的数据库报告工具,基于此数据生成各种类型的报告,如 Crystal Reports 或 Jasper Reports。有关报告数据的其他信息,请参见《Sun Java System Content Delivery Server 5.1 集成和配置指南》中的第 1.5 节“设置定制报告”。
2.2 JMS 客户机应用程序
除了基于 SQL 的事件数据接口,还可以实现通过 JMS 主题与事件服务直接相连的 JMS 客户机应用程序。尽管此方法比较难于实现,但它在使用由 Content Delivery Server 生成的事件方面具有更大的灵活性。
要成功使用此 API 与事件服务集成,您需要熟悉如何编写 JMS 客户机应用程序,并且了解在 Java 2 Platform Enterprise Edition(J2EETM 平台)的 JMS 规范中介绍的发布/订阅消息传送域。任意数量的 JMS 客户机应用程序都可以使用发布/订阅消息传送模型来订阅由事件服务发布的消息。
2.3 事件和事件数据
本节介绍了有关由事件服务提供的事件和事件数据的信息。数据库和 JMS 客户机应用程序都使用此信息过滤和处理事件。客户机应用程序可以根据企业需要处理各种类型的事件。例如,在收到 sms_content_push_sent 事件时,可以执行收费短消息 (premium SMS) 记帐操作。
下表介绍了由事件服务生成的事件。
表 2-4 事件
事件
|
描述
|
content_changed
|
Catalog Manager 管理员对内容进行了更改。
|
content_purchased
|
订户购买了某个内容项或下载了免费的内容项。
|
content_refunded
|
对某个内容项发放了退款。
|
download_deleted
|
从设备中删除了下载的内容。
|
download_error
|
设备指明下载内容时出错。
|
download_initiated
|
订户已开始下载内容。
|
download_install_notified
|
设备已确认下载成功。
|
external_content_updated
|
外部托管内容已更新。
|
gift_cancelled
|
礼品订阅被取消。
|
gift_download_confirm
|
接收者下载了礼品。
|
gift_download_deleted
|
接收者下载的礼品被删除。
|
gift_download_error
|
下载礼品时出错。
|
gift_download_initiated
|
礼品接收者已开始下载礼品。
|
gift_expired
|
礼品已过期。
|
gift_purchased
|
作为礼品购买了某个内容项。
|
gift_refunded
|
对订户购买的礼品发放了退款。
|
gift_subscription_purchased
|
作为礼品购买了某个内容项的订阅。
|
gift_usage_purchased
|
作为礼品购买了对某个内容项的多次使用权。
|
mms_push_sent
|
MMS 消息已发送。
|
pricing_changed
|
已使用“类别价格编辑”功能对一个或多个内容项的价格进行了更改。
|
sms_content_push_sent
|
在 SMS 消息中发送了内容二进制代码。请使用此事件来触发收费短消息 (premium SMS) 记帐。
|
sms_push_sent
|
SMS 消息已发送。
|
sms_received
|
SMS 消息已收到。
|
smtp_push_sent
|
SMTP 消息已发送。
|
status_changed_to_deleted
|
某个内容项的状态被更改为“已删除”。
|
status_changed_to_denied
|
某个内容项的状态被更改为“已拒绝”。
|
status_changed_to_new
|
某个内容项的状态被更改为“新建”。
|
status_changed_to_pending
|
某个内容项的状态被更改为“待定”。
|
status_changed_to_published
|
某个内容项的状态被更改为“已发布”。
|
status_changed_to_testing
|
某个内容项的状态被更改为“测试”。
|
submission_failed
|
提交的内容被 Content Delivery Server 拒绝。
|
submission_successful
|
提交的内容被 Content Delivery Server 接受。
|
subscriber_registered
|
订户已成功注册。
|
subscription_cancelled
|
对某个内容项的订阅被取消。
|
subscription_purchased
|
对某个内容项的订阅被购买。
|
usage_purchased
|
已购买了对某个内容项的多次使用权。
|
validation_passed
|
提交的内容由提交验证器工作流成功处理。
|
validation_failed
|
提交的内容在提交验证器工作流的某个步骤中失败。
|
wap_push_sent
|
WAP 消息已发送。
|
下表列出了可以包含在事件中的信息。每个事件仅包含与该事件相关的参数。
表 2-5 事件数据
参数
|
数据类型
|
描述
|
billing-ticket
|
字符串
|
该事务的记帐凭单。
|
campaign_coupon
|
字符串
|
活动的礼券代号。
|
campaign_id
|
字符串
|
活动的唯一标识符。
|
catalog-res-id
|
字符串
|
内容版的唯一标识符。
|
content_binary_mimetype
|
字符串
|
内容的 MIME 类型。
|
content_class_id
|
字符串
|
内容项的唯一标识符。
|
content_description
|
字符串
|
内容的详细描述。
|
content_drm_type_id
|
字符串
|
标识用于保护内容的 DRM 方法的字符串。
|
content_short_description
|
字符串
|
内容的简短描述。
|
content-id
|
字符串
|
所购买的内容的唯一标识符。此值与 catalog-res-id 相同。
|
content_name
|
字符串
|
内容的名称。
|
current-status
|
字符串
|
事务的当前状态。
|
date
|
日期
|
事务发生的日期。
|
destination-address
|
字符串
|
向其发送内容的地址,例如,请求内容的订户的 MSISDN。
|
developer-content-id
|
字符串
|
开发者用于标识内容的唯一标识符。
|
developer-id
|
字符串
|
内容开发者的唯一标识符。
|
developer_name
|
字符串
|
提交内容的开发者的姓名。
|
download-confirm
|
布尔型
|
表示成功下载后是否需要确认的标志。
|
download-count
|
整型
|
根据支付的价格确定的内容下载次数。
|
download-current-count
|
整型
|
订户下载此内容的次数(包括本次)。
|
download-expiration
|
布尔型
|
表示下载时段是否已过期的标志。
|
download-period
|
整型
|
允许下载内容而无需向订户收取其他费用的时段。
|
download-price
|
浮点型
|
购买内容的价格。
|
download-purchase
|
布尔型
|
用于表示购买请求的标志。
|
download-recurring
|
布尔型
|
表示订户是否为每次下载付费的标志。
|
event-log
|
字符串
|
事件日志的名称。
|
event-msg
|
字符串
|
随事件一起发出的消息。
|
event-source-type-id
|
整型
|
用于标识事件源的编号。
|
event-type
|
整型
|
发生的事件的数字表示。
|
event-type-id
|
字符串
|
发生的事件类型。
|
external_content_id
|
字符串
|
记帐系统用于标识内容的标记。
|
external_group_id
|
字符串
|
记帐系统用于标识内容所属组的标记。
|
external-request-text
|
字符串
|
订户的请求文本,例如,MO 推送请求内容。
|
gift_message
|
字符串
|
礼品中包含的消息。
|
gifted_current_downloads
|
整型
|
接收者下载此礼品的次数(包括本次)。
|
gifted_current_subscriptions
|
整型
|
接收者使用的订阅时段数(包括本时段)。
|
gift_download_date
|
日期
|
接收者第一次下载礼品的日期。
|
gift_expiration_date
|
日期
|
接收者认领礼品的最后期限。
|
gift_purchase_date
|
日期
|
送礼人购买礼品的日期。
|
gifted_downloads
|
整型
|
礼品中包含的下载次数。
|
gifted_subscriptions
|
整型
|
礼品中包含的订阅时段数。
|
is_on_device
|
布尔型
|
表示内容是否已存在于设备中的标志。
|
is-prepay
|
布尔型
|
表示订户是否已为内容预付费的标志。
|
locale
|
字符串
|
订户的语言环境。
|
MSISDN
|
字符串
|
订户设备的 MSISDN。
|
pricingoption_key
|
字符串
|
用于标识价格选项的字符串。
|
pricingoption_name
|
字符串
|
价格选项的名称。
|
push-msgtext
|
字符串
|
发送到订户设备的消息或电子邮件。
|
recipient_locale_code
|
字符串
|
内容预定接收者的语言环境。
|
recipient_login_id
|
字符串
|
内容预定接收者的登录 ID。
|
recipient_mobile_id
|
字符串
|
内容预定接收者的移动 ID。
|
recipient_unique_device_id
|
字符串
|
预定接收者的唯一设备 ID。
|
server-id
|
字符串
|
Vending Manager 的唯一标识符。
|
session-id
|
字符串
|
用于标识订户会话的字符串。
|
source-address
|
字符串
|
从其接收消息的外部实体的地址,例如,SMSC 的 MSISDN。
|
streaming_content_upload_failed
|
字符串
|
此消息表明无法将流式传输内容上载到流式传输服务器。
|
streaming_content_delete_failed
|
字符串
|
此消息表明无法从流式传输服务器中删除流式传输内容。
|
subscription-expiration
|
日期
|
订阅时段结束的日期。
|
subscription-frequency
|
字符串
|
支付订阅费用的时间间隔。
|
subscription-recurring
|
布尔型
|
表示当前订阅时段结束后是否自动为下个时段向订户收费的标志。
|
subscription-price
|
浮点型
|
订阅时段的价格。
|
timestamp
|
时间戳
|
事务发生的时间。
|
unique-device-id
|
字符串
|
所用设备的唯一标识符。
|
usage-count
|
整型
|
根据为 usage-price 指定的价格而确定的使用次数。
|
usage-price
|
浮点型
|
根据为 usage-count 指定的使用次数而确定的支付价格。
|
user-id
|
字符串
|
启动事务的用户的唯一标识符。
|
username
|
字符串
|
订户的登录名。
|
vending-res-id
|
字符串
|
Vending Manager 用于标识内容的标记。
|
2.4 使用事件服务 API
要使用事件服务 API,您需要数据库客户机应用程序或 JMS 客户机应用程序。本节提供了有关根据系统需要开发相应类型客户机的信息。
2.4.1 开发数据库客户机应用程序
应用程序必须获取指向数据库的连接,以便直接查询 Oracle 数据库。具体操作细节取决于数据库服务器和客户机应用程序的本地环境。
有关连接到数据库的信息,请参见 2.1.1 事件表。
2.4.2 开发 JMS 客户机应用程序
要编译 JMS 客户机,请在类路径中包含 JMS 的 Java 归档 (Java Archive, JAR) 文件。此文件位于 /cds-home/deployment/deployment-name/lib/jms.jar,其中 cds-home 是 Content Delivery Server 的安装目录,deployment-name 是为部署指定的名称。
要执行 JMS 客户机,请执行以下操作:
1. 在类路径中包含下表中组件的 JAR 文件。
表 2-6 执行所需的文件
JAR 文件
|
位置
|
JMS
|
/cds-home/deployment/deployment-name/lib/external/javax.jms.jar
|
文件系统上下文(仅当使用 Sun Java System Application Server 时需要)
|
/sun-as-home/imq/lib/fscontext.jar
|
2. 为 execute 命令指定以下选项:
- -Dcds.home=cds-home
- -Dcds.config.file=CDS.properties
- -Dcds.config.dir=cds-home/deployment/deployment-name/conf
2.5 MessageListener 样例实现
以下代码示例是 MessageListener 类的实现。此样例说明了从 CDS 记帐主题接收记帐事件时需要执行的操作。
编码样例 2-1 MessageListener 样例实现
package com.sun.content.server.eventservice.subscriber.internal;
import java.util.Properties;
import javax.jms.*;
import javax.naming.Context;
import javax.naming.InitialContext;
/**
* Attach to the CDS billing topic to receive billing events
*/
public class CDSBillingSubscriber
implements ExceptionListener, MessageListener
{
private static final String kUSAGE = "CDSBillingSubscriber {JNDI Factory} {JNDI URL}";
private static final String kTOPIC_CONNECTION_FACTORY_NAME = "cds.jms.TopicConnectionFactory";
private static final String kTOPIC_NAME = "cds.messaging.billingTopic";
private TopicConnection fConnection;
private TopicSession fSession;
private boolean fDone = false;
public static void main(String[] args)
{
if (args.length != 2)
{
System.out.println(kUSAGE);
System.exit(-1);
}
try
{
CDSBillingSubscriber billingSubscriber = new CDSBillingSubscriber();
billingSubscriber.initJMS(args[0], args[1]);
while (!billingSubscriber.fDone)
{
synchronized (billingSubscriber)
{
System.out.println("Waiting...");
billingSubscriber.wait(1000 * 10);
}
}
}
catch (Exception e)
{
e.printStackTrace();
System.exit(-1);
}
}
/**
* Initialize the JMS topic subscriber
*
* @param jndiFactory the JNDI context factory
* @param jndiProviderUrl the JNDI connection URL
*
* @throws Exception
*/
private void initJMS(String jndiFactory, String jndiProviderUrl)
throws Exception
{
// Initialize the context
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, jndiFactory);
props.put(Context.PROVIDER_URL, jndiProviderUrl);
InitialContext context = new InitialContext(props);
// Get the topic connection factory and topic
TopicConnectionFactory topicConnectionFactory =
(TopicConnectionFactory )context.lookup(kTOPIC_CONNECTION_FACTORY_NAME);
Topic topic = (Topic )context.lookup(kTOPIC_NAME);
// Initialize the topic connection
fConnection = topicConnectionFactory.createTopicConnection();
fConnection.setExceptionListener(this);
// Get a session and subscriber
fSession = fConnection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
TopicSubscriber subscriber = fSession.createSubscriber(topic);
subscriber.setMessageListener(this);
fConnection.start();
}
/**
* Listen for messages asynchronously. Simply print them.
*
* @param message
*/
public void onMessage(Message message)
{
try
{
// simply prints the message
TextMessage txtMsg = (TextMessage )message;
System.out.println(txtMsg.getText());
}
catch (JMSException e)
{
e.printStackTrace();
}
}
/**
* Listen for exceptions and stop waiting
*
* @param jmse
*/
public void onException(JMSException jmse)
{
jmse.printStackTrace();
fDone = true;
this.notifyAll();
}
}
|