IBM Cognos Software Development Kit介绍

1.摘要

    IBM Cognos是一款功能强大的商业智能工具。随着Cognos 在各个行业中被广泛使用,众多企业都开始在Cognos之上进行二次开发,将Cognos融入自己的业务系统中。Cognos SDK (Software Development Kit) 是Cognos二次开发过程中不可或缺的重要工具。绝大多数能通过UI完成的设置,都能通过SDK提供的函数完成。但在实际应用中,开发者会遇见许多经验性的问题,这使得SDK的使用并不是那么得心应手。因此,鉴于目前国内介绍CognosSDK的相关中文资料较少,本文将结合各种应用场景并结合作者在开发中所积累的经验对CognosSDK进行深入浅出的介绍。

    Cognos SDK提供了许多API来对Cognos的方方面面进行操作,大多数能通过Cognos Connection手动完成的设置都可以通过API来完成。Cognos Connection是以Web应用程序的形式部署在应用服务器上的。Cognos通过Web Service和本地的SDK 进行消息沟通。因此在使用Cognos SDK时必须保证Cognos Connection的运行状态良好,而不是处于初始化或者启动失败的状态。

    在Congos的安装目录中( \cognos\webcontent\documentation\en\dg_sdk.pdf),包括了Cognos SDK的开发者指导手册(Developer Guide)。另外在安装CognosSDK之后,会在Cognos安装目录中生成sdk子目录。sdk目录中包括了相关API的说明文档,以及由Java、C#、VB三种语言写成的API使用样例。这些都是利用Cognos SDK进行程序开发的官方指导材料。

    下面以Java程序为例说明如何配置并使用Cognos SDK。在目录(\cognos\sdk\java\lib)中包括sdk的jar包。使用时需要将这些jar包部署在自己的项目中:

▪    新建Java工程(Java Project):例如CognosSample

    图1

▪   在CognosSample之下建立文件夹:例如lib

    图2

▪  将目录(\cognos\sdk\java\lib)中的jar包拷贝到本地目录中(\CognosSample\lib),并配置Java Build Path将jar包纳入项目中:


                                   图3

▪   最后可在项目的lib文件夹中看到被引用的所有jar包。


图4


       事实上一般情况下,只需要加入axis.jar,axisCognosClient.jar,commons-discovery.jar,commons-logging.jar,jaxrpc.jar,saaj.jar这6个包就可以使用绝大多数API。

       对于C#和VB用户来讲,只需要将SDK提供的动态链接库DLL(dynamic link library)文件加入到工程的引用中,就可以正常使用DLL中的函数了。

       

      通过SDK连接Cognos首先要找到BI 服务器的URL超链接地址,例如:“http://localhost:8080/insight/servlet/dispatch”。请注意URL地址不能省略协议前缀“http://”,同时也不能省略servlet的路径。有的时候在Websphere中可以配置URL映射,将“http://localhost:8080/insight”映射到“http://localhost:8080/insight/servlet/dispatch”。但这种短域名无法应用于SDK的操作。

       下面的方法可用于连接Cognos BI服务器。其中通过ContentManagerService_ServiceLocator对象连接Cognos,通过ContentManagerService_Port对象查询或者设置Cognos的内容。通过cmService我们可以查询BI服务器,在这里我们使用“/”符号来查询Cognos BI服务器根目录,服务器受到请求后会返回一个SOAP格式的消息。这样来的以确定BI服务器的运行状态。在下一节中我们会具体说明如何利用ContentManagerService_Port查询以及设置Cognos的内容。

[java]   view plain copy
  1. Public boolean Connect2Cognos(String serverURL)  
  2. {  
  3.         ContentManagerService_Port cmService = null;  
  4.         ContentManagerService_ServiceLocator cmServiceLocator = null;  
  5.         try  
  6.         {  
  7.             cmServiceLocator = new ContentManagerService_ServiceLocator();  
  8.             cmService=cmServiceLocator.getcontentManagerService(new java.net.URL(serverURL));  
  9.         }  
  10.         catch (MalformedURLException e) {  
  11.                 System.out.println("URL地址格式不正确"); //$NON-NLS-1$  
  12.                 return false;  
  13. catch (ServiceException e) {  
  14.                 System.out.println(e.getMessage());  
  15.                 return false;  
  16.         }  
  17.         try {  
  18.                 cmService.query(new SearchPathMultipleObject("/"),//$NON-NLS-1$  
  19.                 new PropEnum[] {}, new Sort[] {}, new QueryOptions());  
  20.         } catch (java.rmi.RemoteException remoteEx) {  
  21.                 //如果设置成身份验证,那么这里就会发生RMI的意外,这个意外可以忽略  
  22.         } catch (java.lang.NullPointerException nullEx) {  
  23.                 System.out.println("Cognos BI Server 连接失败"); //$NON-NLS-1$  
  24.                 return false;  
  25.         }  
  26. }   

                                                              表1

        另外需要注意的是,Cognos 8的SDK并不支持使用HTTPS的URL进行连接,如果您想使用此协议,那么请参考文章【1】,【2】。

      上面的小节提到,Cognos用Web Service在其和SDK之间进行消息交互。在Cognos的安装目录中(\cognos\bin\utilities\diagnostictools)提供了很多实用的小工具,来帮助您管理Cognos。其中通过IBMCognos8CMBrowser1_4(Content Manager Browser Tool)可以显示BI服务器的内容结构,这些内容存储于您在安装Cognos时所建立的内容数据库中(Content Store)。文章【1】介绍了如何使用相关工具探索内容数据库。

                          图5

       从图5中可以看到,内容数据库中的内容实际上是按照树形结构组织的。其中:

         ▪  Administration:中的内容和Public Folders中的内容大体一致,他们描述了现在Cognos系统上的文件夹以及报表目录。

       ▪  Capability:我们知道Cognos有许多组件工具,如报表设计器(ReportStudio),数据管理器(Data Manager)等组成。这里通过Capability显示现有Cognos中哪些组件工具已经被安装并可以使用。

       ▪  Configuration:显示Cognos中现有的配置情况。比如默认用户设置(UserProfile)就保存在这个目录下。通过默认用户设置,你可以为新的用户设置统一的皮肤等。

       ▪  Directory:显示Cognos的安全管理目录。其中“Cognos”这个目录是系统的默认的,这个目录中列出了Cognos所有的角色,以及组别。如果用户自己添加了其他认证方式如NTLM等,也会出现在这个项目下。

       ▪  Portal:它是有关于Cognos Connection的各种可视化选项,比如已安装的样式(Styles)。

        在图5的右侧区域会显示当前选择对象的属性以及值。defaultName(默认名称),hasChildren(是否包含子元素),objectClass(类名),searchPath(查找路径)。通过切换按钮“”,可以显示更多的属性以及值。

        除了searchPath(查找路径),你会发现元素还包括另外一个属性“storeID”,事实上,storeID与searchPath的功能一致。通过它同样可以获取元素的引用的,但是storeID由编码写成,使用时极不方便。因此searchPath是获得Cognos内容对象最理想的方法,下面将对其用法做详细的介绍。

        查找路径(SearchPath)是一个和Cognos存储内容相关的绝对路径。逻辑上他们遵从树形结构,并以“/”符号隔开。除此之外,有些特定的符号约定:

         ▪  “~”: 单纯使用波浪线是可以获取当前Cognos已登录的验证对象。

         ▪  “/”: 单纯使用波浪线表示返回根节点元素。

         ▪  “/*”: 单纯使用它表示返回根节点下的所有元素。

         ▪  “/元素名/元素名”: 例如:“/portal/portalSkinFolder”

         ▪  “元素名/*”: 返回该元素下的所有子元素。例如:“/portal/portalSkinFolder[@name='Styles']/*”。获得Cognos BI服务器的所有皮肤样式。

         ▪   “//元素名”: 返回所有元素名相同的对象。比如Cognos的对象有account ,role,group等,且他们分散在不同的命名空间(namespace)下,这时我们就可以通过“//account”获得所有的账户对象。

         ▪  “//*”: 以BaseClass的对象数组形式,返回内容存储库中的所有元素。

        其他特定元素的查找路径都可以在Content Manager Browser Tool的元素属性中查到。如何利用查找路径来获取元素呢?这里就要用到我们在第四章提到的ContentManagerService_Port对象。

[java]   view plain copy
  1.        public BaseClass[] query(ContentManagerService_Port cmService, String searchPath) {  
  2.     PropEnum props[] = new PropEnum[] { PropEnum.searchPath,  
  3.             PropEnum.options, PropEnum.defaultName};  
  4.     BaseClass[] results = null;  
  5.     SearchPathMultipleObject cmSearchPath = new SearchPathMultipleObject(  
  6.             searchPath);  
  7.     try {  
  8.         results = cmService.query(cmSearchPath,  
  9.                 props, new Sort[] {}, new QueryOptions());  
  10.         return results;  
  11.     } catch (java.rmi.RemoteException remoteEx) {  
  12.         remoteEx.printStackTrace();  
  13.         return null;  
  14.     }  
  15. }  

                    表2

        从表2的程序中可以看到,实际的查找操作是通过ContentManagerService_Port的query方法来完成的,而查找的内容就是用我们先前提到的searchPath字符串来指出。searchPath必须用SearchPathMultipleObject对象包装起来才能供ContentManagerService_Port使用。

        查询的结果是BaseClass,他是Cognos所有对象的基类。在获取BaseClass之后,用户可以根据自己的需要将它强制转换(Down-Cast)为BaseClass的子类。事实上,每个子类的属性都不一样。如果查询的时候返回所有的属性就会对网络资源造成不必要的浪费,不要忘了SDK是通过SOAP来与Cognos进行交互。因此可以通过枚举类型PropEnum设置我们需要获取的属性。只获取我们需要的属性值,从而优化SOAP的传输。最常用的属性值包括:PropEnum.searchPath(对象的查找路径),PropEnum.defaultName(对象的默认名称),以及PropEnum.options(对象的选项)等。

        除了查找操作,我们同时希望将更改过的结果应用于Cognos系统中。这个操作同样是通过ContentManagerService_Port对象完成。通过表3可以看到,只要将需要更新的对象以BaseClass对象数组的形式传递给update方法即可。

[java]   view plain copy
  1.        public void updateAccount(ContentManagerService_Port cmService, BaseClass[] objs) {  
  2.     try {  
  3.         cmService.update(objs,new UpdateOptions());  
  4.     } catch (java.rmi.RemoteException remoteEx) {  
  5.         remoteEx.printStackTrace();  
  6.     }  
  7. }  

                                                                                             表3

         Cognos BI服务器初始化过程需要花费一定的时间。我们通过SDK的所有操作都要在BI服务器正常运行的状态下才能处理,那么如何通过SDK检查BI服务器的状态呢?

[java]   view plain copy
  1. public boolean isRunning(ContentManagerService_Port cmService){  
  2.         try {  
  3.             cmService.query(new SearchPathMultipleObject("/"),  
  4.                     new PropEnum[] {}, new Sort[] {}, new QueryOptions());  
  5.         } catch (java.rmi.RemoteException remoteEx) {  
  6.   
  7.         } catch (java.lang.NullPointerException nullEx) {  
  8.             System.out.println("Cognos BI 服务器连接失败");   
  9.             return false;  
  10.         }  
  11.         //获得返回的SOAP消息头,  
  12.         BiBusHeader bibus = (BiBusHeader) ((Stub) cmService).getHeaderObject("""biBusHeader");  
  13.         if (bibus == null) {  
  14.             System.out.println("Cognos BI 服务器连接失败"); //$NON-NLS-1$  
  15.             return false;  
  16.         }if (bibus != null) {  
[java]   view plain copy
  1. <p>                // 如果能通过bibus获取CAM对象,则证明</p><p>                if (bibus.getCAM() != null) {</p><p>                return true;</p><p>                }</p><p>           }</p><p>           return false;</p><p>       }</p>  
                                                                                                 表4
         通过查询BiBusHeader中的CAM(Cognos Asset Manager)对象,我们就可以获得Cognos服务器的运行状态,而在Cognos服务器初始化阶段,CAM对象是无法被获取的。在获取BiBusHeader之前必须执行一次query,这样服务器才能返回SOAP消息。


        使用SDK登陆Cognos的代码和文章很容易在网络中,或者SDK附带的程序中找到,因此不再赘述。这里只分享登录过程中的有关注意事项。

        首先,我们知道Cognos允许使用匿名用户(anonymous)登录,这一点也会在SDK登录中体现。使用“/”来获取BaseClass对象,如果获取的结果不为空,则表明Cognos此时允许匿名用户登录。

        在Cognos SDK附带的程序中,如果使用用户名密码登录,则程序会验证当前Cognos中的命名空间(Namespace),如果命名空间不存在则无法登录。笔者发现当您在开启匿名登录的情况下,是查询不到系统中的命名空间的。那么这是不是意味着在匿名登录开启的情况下,SDK就无法通过用户名密码登录了呢?答案是否定的,经过笔者的实践,验证命名空间的步骤并不是登录必须的,也就是说我们可以忽略它,直接使用命名空间的名称来登录系统。


        Cognos提供了较为完备的用户权限管理系统。Cognos自己的系统安全控制层次包括角色(Role):如系统管理员(System Administrators)等,组(Group):如任何人(Everyone),以及账户(Account):如匿名用户(Anonymous)。这类似于Windows的NTLM验证方式。每一个登录的实际用户都属于账户级别,账户可以被加入到组中方便管理。而组可以被设置为角色的成员以分配特定的权限。

        有的时候我们需要检查用户的身份,以判断用户是否有够权限去完成特定的操作。这些如何通过Cognos SDK完成呢?下面以验证用户或者组是否在系统管理员的角色中为例。

[java]   view plain copy
  1.       public boolean isSysAdmin(CMConnection conn,String userPath){  
  2. PropEnum props[] = new PropEnum[] { PropEnum.members };  
  3. BaseClass[] sysAdmins = query(conn, "CAMID('::System Administrators')",props);  
  4. Role sysAdmin = (Role)sysAdmins[0];  
  5. //获取系统管理员下的各个组  
  6. BaseClass[] sysAdminMembers = sysAdmin.getMembers().getValue();  
  7. if(sysAdminMembers == null)return false;  
  8. //遍历每个组  
  9. for(int i=0;i<sysAdminMembers.length;i++){  
  10.     if(sysAdminMembers[i].getSearchPath() == null)  
  11.         return false;  
  12.     String groupPath = sysAdminMembers[i].getSearchPath().getValue();  
  13.     if(groupPath.contains(userPath)) return true;  
  14.     BaseClass[] groups = query(conn, groupPath, props);  
  15.     if(groups.length == 0continue;  
  16.     Group group = (Group)groups[0];  
  17.     //获取组内的成员  
  18.     BaseClass[] userMembers= group.getMembers().getValue();  
  19.     if(userMembers == null)continue;  
  20.     for(int j=0;j<userMembers.length;j++ ){  
  21.         if(userMembers[j].getSearchPath()==nullcontinue;  
  22.        if(userMembers[j].getSearchPath().getValue().contains(userPath))  
  23.        return true;  
  24. }}  
  25. return false;  
                                                                                   表5

        在Cognos中,命名空间(Namespace)并不会直接加入到角色(Role)的成员(Members)中,Cognos会让用户选择将命名空间中的某个组设置为组的成员。比如我们可以讲Windows NTLM的administrators组加入到Cognos的系统管理员(SystemAdministrators)的成员中。那么如何验证当前登录的用户是否为系统管理员呢?首先我们可以通过查找路径“~”获得当前已登录系统的用户账户对象(Account),这样就可以获得此用户的查找路径(SearchPath)。查找路径在Cognos中具有唯一性,因此可以用来标识用户的唯一性。要判断一个组具有系统管理员权限,我们可以用组名和系统管理员的成员(Members)相比较。要判断用户是否具有系统管理员权限,我们可以将用户(User)的查找路径取出并和系统管理员成员组中的用户的查找路径相互比较,看看是否一致。听起来有点儿拗口吧?但逻辑实现却比较清晰,我们来分析一下。

       表5中的参数userPath可以为组名比如说Everyone,也可以是用户的查找路径。系统管理员的查找路径为“CAMID('::System Administrators')”,由此我们可以获得系统管理员对象的引用以及他的成员,但别忘了将PropEnum.members加到查找条件中获得成员组后,可以继续查找成员组有哪些成员用户,并用这些用户的查找路径和输入的路径进行比较。

        这里有个需要注意的地方。Cognos在不同的操作系统中,有些对象的查找路径会被相应的本地化。比如,英文系统中的目录管理员角色“Directory Administrators”的查找路径就会被本地化为“CAMID('::目录管理员')”,如图6所示。但有一些就不会被本地化比如系统管理员,以及所有人(Everyone)等。这点非常重要,如果不注意会造成同样的程序在不同的操作系统中表现出意外的结果。您可以打开Cognos自带的内容管理器浏览工具来确定对象的具体查找路径。

                                                                                                   图6

【1】      SDK Sample on how to set an SDK application to connect to SSLconfigured IBM Cognos

https://www-304.ibm.com/support/docview.wss?uid=swg21381936

【2】How to set an SDK application to connect to SSL configured ReportNetor Cognos 8

https://www-304.ibm.com/support/docview.wss?uid=swg21367416

【3】Understand your CognosContent Store database using Content Manager Size and Browser Tool

http://www.ibm.com/developerworks/data/library/techarticle/dm-0808masters/index.html

【3】IBM Cognos 8 的整体外观定制与实践

http://www.ibm.com/developerworks/cn/data/library/techarticles/dm-1007linhx/index.html

【4】Changing Skins ForCognos 8 in Cognos Connection

https://www-304.ibm.com/support/docview.wss?uid=swg21341062


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值