注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

风之泪

风过雨过,花开花落。。。

 
 
 

日志

 
 

Cognos 8 SDK 在 Web 应用中集成 Cognos 报表  

2011-04-08 11:38:36|  分类: cognos |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

Cognos 8 SDK 简介

Cognos 8 SDK 从功能上可以分成三部分:BI Bus API,URL Interface 和 Script. Player。

BI Bus API

Cognos 8 通过提供的 BI Bus API 将相关服务整合到其他应用软件中去。Cognos 8 SDK 体系结构是建立在基于 WSDL 和 SOAP 的 web service 基础上的。Cognos.wsdl 文件中具体描述了 Cognos 所提供的各种服务及其支持的方法。用户请求通过 SOAP 包传递于服务器和客户端之间。SDK 提供的接口使开发者不必亲自构建 SOAP 消息。调用接口时,SDK 负责将用户请求转化成 SOAP 消息,再通过 BI Bus API 传递给相应的服务。BI Bus API 将每个 XML 格式的 request 或 response 包装进 SOAP 信封,并通过 HTTP 协议传输。

URL Interface

URL Interface 使用户可以通过在 URL 中传递命令及参数来实现相应的 Cognos 操作。

Script. Player

Script. Player 是一种命令行工具,用于执行编制好的 action logs,实现 Framework Manager 设定的功能,如创建和修改模型,或者部署 package 等。

准备使用 Cognos 8 SDK

将 Portal server 与 Cognos 8 集成时,可以有多种方式。如使用 Web Page Portlet,将 Cognos 报表的链接直接嵌入到 Portal 的页面里,或者直接部署 Cognos 8 提供的 Portlet。使用这些 Portlet 可以在 Portal 中查看 Cognos 报表,metrics 等。这两种方式都提供了展示和查看 Cognos 中已有内容的功能,虽然可以使用 WebSphere Dashboard 快速开发 Cognos Portlet,但这仅能提供有限的灵活度,且需基于 Portal,无法满足部分客户定制化的需求。这时就需要使用 Cognos 8 SDK 来进行相应的开发工作,更灵活的实现与 Cognos 的整合。下面就来介绍下如何使用 Cognos 8 SDK 实现 Cognos 与 Web 应用的整合。

安装 Cognos 8 SDK 和 Cognos 8 Samples

Cognos 8 SDK 是 Cognos 8 的一个独立组件,需要单独安装。安装完成后,SDK 相关的内容默认被添加到 Cognos 8 的安装目录下,其中包含了 C#,VB 和 Java 的运行时内容及相关的文档和示例。为了配合本文写作,还需安装 Cognos 8 Samples 组件,请参阅向导完成安装配置并将示例数据倒入到 DB2 数据库中。我们将在本文介绍 SDK 中 Java 相关部分,并使用 Samples 中名为 great_outdoors_sales 的示例模型与数据。

修改和部署模型

准备工作完成后可以在目录cognos_home\c8\webconetnt\samples\models\下看到名为 greate_outdoors_sales 的示例模型目录。Cognos 8 SDK 提供了 Script. Player 用于创建和修改模型,我们可以将这部分功能集成到 Web 应用中,其核心工作是编写 XML 格式的 action log 文件,以实现对模型的操作,但本例将重点放在对报表的创建及展示,所以将忽略这部分内容,而直接使用 Framework Manager 对 great_outdoors_sales 的模型进行修改。在 Framework Manager 中打开 great_outdoors_sales.cpf。


图 1. 模型项目 go_sales
图 1. 模型项目 go_sales

可以看到示例项目 go_sales 中已经有建好的 Go_sales(analysis) 和 Go_sales(query) 两个 package,其中引入了大量的业务对象。为了简单,我们将重新定制 package, 仅引入少数所需要的业务对象。右键点击 Packages,选择 Create->Package,输入名字:CognosSample;点击 Next;如下图所示,选择本例中需要使用的业务对象:


图 2. 创建 package
图 2. 创建 package

在接下来的设定中,选择英文作为支持语言,DB2 作为功能集,完成并打开发布向导。将 package 发布到 content store 中,不使用模型版本。本例中不引入安全机制,接受默认设定,直到完成发布。

Cognos 8 SDK 使用实例

至此,我们已经可以通过 Query Studio 和 Report Studio 直接使用 package 中相应数据创建报表和查询了,但本文意在说明 SDK 的使用,下面我们就使用 SDK 开发一个基于 Web 生成 Cognos 报表的应用,来展示如何利用 Cognos SDK 生成一个简单的二维报表及其对应的柱状图。用户可以从模型中选择报表中的行和列(Dimension),以及度量(Measure)。

获取服务

首先根据需要创建 Web 应用项目,并将应用需要依赖的 library 引入项目,将cognos_home\c8\sdk\java\lib\目录下的 jar 文件复制到 Web 项目的 lib 目录下,这样我们就可以在 Web 应用中使用 Cognos 8 SDK 了。首先要建立与 Cognos 所需服务的连接,在 Cognos SDK 里,不同的功能是由不同的服务提供的,例如提供管理内容和认证服务的 Content Manager service,管理报表服务的 Report service。每一个服务都是通过相应的一组 java 接口调用 BI Bus API 实现的。其中最主要的接口类是 [service]_Service 和 [service]_Port。[service]_ServiceLocator 是 [service]_Serviced 的实现类,通过 [service]_ServiceLocator 可获得具体服务的 [service]_Port,通过 [service]_Port 我们就可以而调用服务所提供的相应功能了。

如下代码展示了如何获得 report service port:


清单 1. 获取 report service port

// 实例化所需服务的 ServiceLocator    ReportService_ServiceLocator reportLocator = new ReportService_ServiceLocator();    // 通过 ServiceLocator 获得 ServicePort    ReportService_Port reportService =     reportLocator.getreportService("http://localhost:9300/p2pd/servlet/dispatch");

获取模型列表

接下来我们就要获得所有已经发布的模型,展示在页面上供用户选择,如下图所示:


图 3. 模型列表
图 3. 模型列表

我们需要使用 Content Manager service 的查询功能,其查询功能主要由query(SearchPathMultipleObject searchPath, PropEnum[] properties, Sort[] sortBy, QueryOptions options)方法实现,其中:

  • SearchPathMultipleObject参数指明要查找对象的路径,搜索路径在 Cognos 8 SDK 中的使用是非常广泛而且重要的,它遵循 XPath 的语法,如要搜索公共目录的根路径为/content/,这里我们要查找公共目录中的所有 package 对象,而不考虑 package 的具体位置,将搜索路径就设成/content//package。若需要访问特定用户的目录,则需要通过用户的 Account 对象,获取其搜索路径,如:[account].getSearchPath().getValue()+”folder[@name=\”My Folders\”]”
  • PropEnum指明要查找对象具体哪些属性。
  • Sort是指明返回对象的排序规则,可以设定是按照哪个 PropEnum 属性排序,通过其中的 OrderEnum 指明是正序还是倒序。
  • QueryOptions指明本次查询的参数,例如是同步查询还是异步查询。

例子中我们搜索公共目录下所有 package 对象,返回相应的 defaultName 和 searchPath,即模型名称和是模型具体的查询路径。采用默认排序和默认查询属性。我们将查询到的所有模型对象放入一个 HashMap 对象,从而在 web 页面展示给用户。代码如下:


清单 2. 获取模型

//Get ContentManagerService    ContentManagerService_Port cms = getContentManagerService();    //Query model objects    BaseClass baseClassArray[]            = cms.query(new SearchPathMultipleObject("/content//package"),     new PropEnum[]{     PropEnum.defaultName,     PropEnum.searchPath},     new Sort[]{},     new QueryOptions());        //Put model name and path in to a hashmap    HashMap<String, String> models = new HashMap<String, String>();    for (BaseClass baseClass : baseClassArray) {     if(baseClass.getClass().getName()     .equals("com.cognos.developer.schemas.bibus._3._package")){     models.put(baseClass.getDefaultName().getValue(),    baseClass.getSearchPath().getValue());     }    }

获取模型的元数据

当用户选择了一个具体模型,我们要获得其选中模型的元数据,并显示成列表供用户选择,组成报表的行,列和度量。如下图所示:


图 4. 模型元数据
图 4. 模型元数据

模型元数据的获取需要通过 report service。首先我们要组织查询元数据的 xml 格式的字符串。元数据查询 xml 字符串是以 metadataRequest 作为 root 结点,此结点有 connection 属性,其值就是我们通过上一步骤获得的 searchPath。此外我们就要通过一个或多个 <Propertie> 结点指明要查询模型的属性。在本例中我们要查询模型 folder,querySubject 以及 queryItem 结点的 name,datatype,_path,_ref 和 usage 属性。

  • queryItem结点是 folder 结点和 querySubject 结点的子节点,其中所包含就是模型文件中的具体数据项。
  • name属性是数据项的名字,用来显示在 web 界面。
  • dataType属性指明此数据项的数据类型。例如是字符或者数字等。
  • _Path属性指明此数据项的查询路径。
  • _ref属性指明此数据项在模型中的路径。
  • usage属性指明此数据项的使用类型,例如度量或维度等。

查询字符串如下:


清单 3. 模型元数据查询字符串

String modelPath =   "/content/folder[@name='Samples']/folder[@name='Models']/package[@name='CognosSample']"   String sXML = "<metadataRequest connection=\"" + modelPath + "\">"    + "<Metadata>"    + "<Properties>"    + "<Property name='*/@name'/>"    + "<Property name='*/@datatype'/>"    + "<Property name='*/@_path'/>"    + "<Property name='*/@_ref'/>"    + "<Property name='*/@usage'/>"    + "<Property name='./folder'/>"    + "<Property name='./querySubject'/>"   + "<Property name='./queryItem'/>"    + "</Properties>"    + "</Metadata>"    + "</metadataRequest>";

组织好 metadataRequest 查询字符串后,我们就要通过调用 report service 的runSpecification(AsynchSpecification specification, ParameterValue[] parameterValues, Option[] options)方法获得所需模型的元数据。

  • AsynchSpecification就是我们所生成的 metadataRequest 查询字符串。
  • ParameterValue当我们要生成具体的报表,而且此报表需要参数时,通过 ParameterValue 指明参数。
  • Option指明运行的参数,例如是同步还是异步。

代码如下:


清单 4. 获取模型元数据代码

// 通过上面生成的 metadataRequest 查询字符串创建 ReportServiceMetadataSpecification 对象。   ReportServiceMetadataSpecification metadataSpec =    new ReportServiceMetadataSpecification();    metadataSpec.setValue(new Specification(sXML));    // 运行 report service 的 runSpecification 方法   AsynchReply runResponse = conn.getReportService()     .runSpecification(metadataSpec, new ParameterValue[]{}, new Option[]{});        // 获取模型的元数据   AsynchDetailReportMetadata reportMetadata;    boolean foundMetadata = false;    String sMetaData = "";    for(int i=0; i<runResponse.getDetails().length && !foundMetadata; i++) {     if (runResponse.getDetails()[i] instanceof AsynchDetailReportMetadata) {     foundMetadata = true;     reportMetadata = (AsynchDetailReportMetadata) runResponse.getDetails()[i];     sMetaData = reportMetadata.getMetadata().toString();     }    }

我们获得的模型元数据是以 xml 格式存储的,所有的 queryItem 结点就是我们报表需要的数据,其中usage="3"的结点可以作为报表的度量,其余结点可以作为报表的行或者列。如下所示:


清单 5. 模型元数据

<ResponseRoot>     <folder _path="[go_sales]" _ref="[go_sales]" name="go_sales">     <folder _path="[go_sales].[Sales (query)]"    _ref="[Sales (query)]" name="Sales (query)">     <querySubject _path="[go_sales].[Sales (query)].[Sales]"    _ref="[Sales (query)].[Sales]" datatype="0" name="Sales">     <queryItem _path="[go_sales].[Sales (query)].[Sales].[Quantity]"    _ref="[Sales (query)].[Sales].[Quantity]" datatype="11"    name="Quantity" usage="3"/>     <queryItem _path="[go_sales].[Sales (query)].[Sales].[Unit cost]"    _ref="[Sales (query)].[Sales].[Unit cost]" datatype="20"    name="Unit cost" usage="3"/>     <queryItem _path="[go_sales].[Sales (query)].[Sales].[Unit price]"    _ref="[Sales (query)].[Sales].[Unit price]" datatype="20"    name="Unit price" usage="3"/>     <queryItem _path="[go_sales].[Sales (query)].[Sales].[Unit sale price]"    _ref="[Sales (query)].[Sales].[Unit sale price]" datatype="20"    name="Unit sale price" usage="3"/>     </querySubject>     <querySubject _path="[go_sales].[Sales (query)].[Branch]"    _ref="[Sales (query)].[Branch]" datatype="0" name="Branch">     <queryItem _path="[go_sales].[Sales (query)].[Branch].[Branch code]"    _ref="[Sales (query)].[Branch].[Branch code]" datatype="11"    name="Branch code" usage="2"/>    <queryItem _path="[go_sales].[Sales (query)].[Branch].[Address 1]"    _ref="[Sales (query)].[Branch].[Address 1]" datatype="96"    name="Address 1" usage="7"/>     <queryItem _path="[go_sales].[Sales (query)].     [Branch].[Address 1 (multiscript)]"    _ref="[Sales (query)].[Branch].[Address 1 (multiscript)]"    datatype="96" name="Address 1 (multiscript)" usage="7"/>     </querySubject>     </folder>     </folder>     <package name="CognosSample"/>    </ResponseRoot>

另外需要指明的是,cognos 的范例模型是支持多语言的,所以我们在页面增加了语言下拉框用来展示如何通过 cognos SDK 生成多语言的报表。如下所示:

<select name="language" id="language">     <option value='en' >English</option>     <option value='zh' >Chinese</option>    </select>

生成报表

当用户指明了报表中的行,列和度量,我们就可创建报表了。生成报表可分为两个步骤,第一步是要组织报表说明 (report specification),第二步就是通过 report service 生成报表。

组织报表说明

在 Cognos 中,报表说明文件包含了对报表的所有设定,从数据内容到外观样式。报表说明是一个 xml 格式的文件,其根节点为<report xmlns="http://developer.cognos.com/schemas/report/6.0/">,其主要包含三部分:

1.<modelPath>结点指明用来生成报表的模型的路径。就是我们通过 Content Manager service 获得的模型的 searchPath。在报表模型中如下表示:

<modelPath>/content/folder[@name='Samples']/folder[@name='Models']      /package[@name='SampleModel']/model[@name='model']</modelPath>

2.<queries>结点指明报表所需的数据项以及在模型中的路径。这部分信息可以通过我们获得的模型元数据中得到。本例中的报表需要三个数据项分别表示报表中二维表的行,列和度量。所以如下所示总共有三个 <dataItem> 结点,其 name 属性的值为模型元数据中 <queryItem> 结点 name 属性的值。<expression> 结点的值就是模型元数据中 <queryItem> 的 _ref 属性的值。

<queries>     <query name="Query1">     <source>     <model/>     </source>     <selection>     <dataItem name="Unit cost">    <expression>[Inventory (query)].[Inventory].[Unit cost]</expression>     </dataItem>     <dataItem name="Country">     <expression>[Inventory (query)].[Branch].[Country]</expression>     </dataItem>     <dataItem name="Product brand">    <expression>[Inventory (query)].[Product].[Product brand]</expression>     </dataItem>     </selection>     </query>    </queries>

3.<layouts>结点指明报表的结构,也就是最终用户所看到报表的样子。本文以 CrossTab 表和柱状图为例进行介绍。

  • 柱状图部分的定义包含在 <combinationChart refQuery="Query1" name="Combination Chart1"> 结点之中,其主要包含三个部分。

    <combinationChartTypes> 通过 <bar> 结点指明了此图为柱状图,而且柱状图的柱状部分从数据项 <chartNodeMember refDataItem="Product brand"> 取值。

    <combinationChartTypes>     <bar>     <chartNodes>     <chartNode>     <chartNodeMembers>     <chartNodeMember refDataItem="Product brand">     < 省略… >     </chartNodeMember>     </chartNodeMembers>     </chartNode>     </chartNodes>     </bar>    </combinationChartTypes>

    通过 <defaultChartMeasure refDataItem="Unit cost"/> 结点定义了柱状图的度量部分所用数据项。

    通过 <chartNodeMember refDataItem="Country"> 结点定义了柱状图的纵坐标部分所用数据项。

    <commonClusters>     <chartNodes>     <chartNode>     <chartNodeMembers>     <chartNodeMember refDataItem="Country">     < 省略… >     </chartNodeMember>     </chartNodeMembers>     </chartNode>     </chartNodes>    </commonClusters>

  • CrossTab 表的定义包含在 <crosstab refQuery="Query1" name="Crosstab1"> 结点之中,其主要也包含三个部分。

    通过 <crosstabCorner> 和结点定义表的度量,其使用的数据项通过 <dataItemLabel refDataItem="Unit cost"/> 结点和 <defaultMeasure refDataItem="Unit cost"/> 结点定义。

    <crosstabCorner>     < 省略… >     <contents>     <textItem>     <dataSource>     <dataItemLabel refDataItem="Unit cost"/>     </dataSource>     </textItem>     </contents>    </crosstabCorner>    < 省略… >    <defaultMeasure refDataItem="Unit cost"/>

    通过 <crosstabColumns> 结点定义表的列,其使用的数据项通过 <crosstabNodeMember refDataItem="Country"> 结点定义。

    <crosstabColumns>     <crosstabNode>     <crosstabNodeMembers>     <crosstabNodeMember refDataItem="Country">     < 省略… >     </crosstabNodeMember>     </crosstabNodeMembers>     </crosstabNode>    </crosstabColumns>

    通过 <crosstabRows> 结点定义表的行,其使用的数据项通过 <crosstabNodeMember refDataItem="Product brand"> 结点定义。

    <crosstabRows>     <crosstabNode>     <crosstabNodeMembers>     <crosstabNodeMember refDataItem="Product brand">     < 省略… >     </crosstabNodeMember>     </crosstabNodeMembers>     </crosstabNode>    </crosstabRows>

此外,报表说明文件中还可以定义其它有关报表样式的内容。实际应用中可以通过定制不同的报表样式模板供用户选择以实现定制化,或对其中的细节设定提供定制,由用户自由选择生成模板,进而生成定制化的报表。出于简明,本文使用固定模板,不详细介绍界面的定制功能。

至此,我们了解了一个报表说明文件的框架内容,之后我们就可以开发相应代码来根据用户选择的行,列和度量生成实际的报表说明文件。由于报表说明是一个 xml 格式的文件,所以本例中我们选用 dom4j API 来生成报表说明。下面简要说明一下生成报表说明的方法,具体请参考附件中的Report.java类。其主要分成三部分,分别生成上文介绍的三个部分:

1.addModelPath(String modelPath):生成模型路径结点。

2.addDataItem(String name, String expression):生成数据项结点。

3. 柱状图 :

  • makeChartNodes(String name):生成柱状图结点。
  • addChartRow(String name):生成柱状图行结点。
  • addChartColumn(String name):生成柱状图列结点。
  • addChartMeasure(String name):生成柱状图度量结点。

CrossTab:

  • makeCrosstabNode(String dataItem):生成 CrossTab 结点。
  • addCrosstabRow(String dataItem):生成 CrossTab 的行结点。
  • addCrosstabColumn(String dataItem):生成 CrossTab 的列结点。
  • addCrosstabMeasure(String dataItem):生成 CrossTab 的度量结点。

生成报表

当我们准备好了报表说明文件,就可调用 report service 生成报表。

1. 准备参数:

首先我们要通过上一步的创建的 xml 报表定义生成 Specification 对象。

Specification spec=new Specification(new XmlEncodedXML(getXML()));    ReportServiceReportSpecification reportSpec = new ReportServiceReportSpecification();     reportSpec.setValue(spec);

然后设置 RunOptionBoolean 对象的 RunOptionEnum.saveOutput 属性为 false,表示我们只生成报表而不保存报表定义。

RunOptionBoolean saveOutput = new RunOptionBoolean();    saveOutput.setName(RunOptionEnum.saveOutput);     saveOutput.setValue(false);

接下来我们通过设置 RunOptionStringArray 对象的 RunOptionEnum.outputFormat 属性来指明我们所要输出的报表格式,在本例中我们通过 web 页面来展示报表,所以选择 HTMLFragment 输出格式。

RunOptionStringArray utputFormat = new RunOptionStringArray();    outputFormat.setName(RunOptionEnum.outputFormat);     outputFormat.setValue(new String[]{"HTMLFragment"});

最后我们通过设置 RunOptionLanguageArray 对象的 RunOptionEnum.outputLocale 指明报表的语言,其值就是用户页面选择的语言。

RunOptionLanguageArray utputLocale = new RunOptionLanguageArray();    outputLocale.setName(RunOptionEnum.outputLocale);     outputLocale.setValue(new String[]{locale});

2. 调用 report service:

调用 report service 的 runSpecification 方法,传入上一步准备的参数。

AsynchReply report = conn.getReportService().runSpecification(    reportSpec,     new ParameterValue[]{},     new Option[]{saveOutput, outputFormat, outputLocale});

获得报表内容。报表内容如果很多,一页显示不下的情况下,Cognos 会把报表分在几个页里显示,在此例中我们只返回报表的第一页。

AsynchDetail[] details = report.getDetails();    for (AsynchDetail detail : details) {     if (detail instanceof AsynchDetailReportOutput) {     return ((AsynchDetailReportOutput) detail).getOutputPages()[0];     }    }

如要获得报表的下一页,可调用 report service 的 nextPage() 方法。另外对于页数很多的报表,为了方便用户定位报表的不同页面,report service 还提供了 previousPage(),firstPage(),lastPage() 方法。

下图是用户选择 CognosSample 模型,Year 作为行数据,Product line 作为列数据,Unit price 作为度量,语言为英文所生成的报表。


图 5. 英文柱状图和报表
图 5. 英文柱状图和报表

如下是相同数据,选择中文所生成的报表:


图 6. 中文柱状图和报表
图 6. 中文柱状图和报表

总结

本文介绍了如何使用 Cognos 8 SDK 在 Web 应用中定制一个简单的报表。实际应用中,SDK 还可以用于在 Web 应用中实现用户权限控制,为用户保存定制化的报表,定期执行查询等功能。实际上,如果需要的的话,所有需要通过 Cognos 图形界面来完成的工作都可以通过 Cognos 8 SDK 在定制的 Web 应用中去完成。

 

转自:http://www.ibm.com/developerworks/cn/data/library/techarticles/dm-0912wangd/index.html

  评论这张
 
阅读(1972)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017