将用于访问 SalesForce.com 数据的移动应用程序与 IBM Worklight 和 IBM WebSphere Cast Iron 相集成

如何构建一个移动应用程序,从客户关系管理系统中检索信息?使用 IBM® Worklight 和 WebSphere® Cast Iron 解决方案,您将学习如何轻松且快速地为连接到 WebSphere Cast Iron 的任何类型智能电话或平板电脑部署一个移动应用程序,从而处理 SalesForce®.com 数据。

Magali Boulet, 认证的客户端技术专家, IBM

Magali Boulet 是一名认证的客户端技术专家,自 2006 年以来一直就职于 IBM。她的工作主要集中于为各行各业的客户解决有关 WebSphere DataPower 和 WebSphere Cast Iron 方面的问题。在加入 IBM 之前,Magali 曾在多家 IT 公司工作过。



Etienne Noiret, WebSphere 解决方案架构师, IBM

Etienne Noiret 在 BPM 领域使用不同技术工作了 6 年多。他还担任过 6 年的 Java EE 架构师。使用 Java 和 Flex 开发了一些原生移动接口之后,他发现使用 Dojo 进行开发非常容易!



2013 年 2 月 28 日

免费下载:IBM® Worklight Mobile Platform
下载更多的 IBM 软件试用版,并加入 IBM 软件下载与技术交流群组,参与在线交流。

简介

公司正在努力削减成本,提高生产力和迅速提供新功能,以便获得最大数量的用户和市场。云计算和移动是帮助您满足这些需求的两大技术驱动要素。正因如此,IBM 将 Worklight(一个移动企业应用程序平台)和 IBM WebSphere Cast Iron(一个云集成解决方案)一起放在 IBM Mobile Foundation 中,提供了一个全面的端到端解决方案来构建、连接、管理和保护您的移动企业。IBM Endpoint Manager for Mobile Devices 是 IBM Mobile Foundation 的第三个组件,可帮助您管理和保护移动设备。但是,此组件不属于本文的讨论范围。本文的目的是证明您可以使用 IBM Worklight 和 WebSphere Cast Iron 轻松地将移动应用程序连接到 CRM,比如 SalesForce.com。

IBM Worklight 支持执行丰富、跨平台的应用程序开发来满足移动企业的需求。通过利用标准技术和工具,比如 HTML5、CSS 和 JavaScript,IBM Worklight 的开放方法支持组织为广泛的智能电话和平板电脑开发丰富的 HTML5、混合和原生应用程序。

IBM Worklight 包含移动优化的中间件,这些中间件可用作应用程序、企业后端系统和云服务之间的网关。IBM Worklight 旨在与组织的现有基础架构相集成,并利用它们的现有资源和流程。

IBM WebSphere Cast Iron 解决方案是一个单一、完整且健全的平台,专为满足连接您的所有云应用程序、所有内部应用程序和两组应用程序的任何合并式组合的具体需求而设计。Cast Iron Cloud 集成简化了数据迁移和应用程序集成,提供了使用一种 “配置而非编码” 方法完成这样的项目所需的所有内容,这种方法不需要专业程序员或中间件专业化。

在本文中,您将学习如何将 Worklight 的生产力与 Cast Iron 的易用性相结合,构建出一个检索 SalesForce.com 信息的移动应用程序。


场景概述

您将使用 Worklight 和 Cast Iron 解决方案构建一个移动应用程序。这个移动应用程序将显示 SalesForce.com 帐户。对于选定的每个帐户,它将显示关联的 SalesForce.com 联系人。

此场景包含 3 个组件:

  • Worklight 用于构建移动应用程序
  • Cast Iron 用作连接到 SalesForce.com 的中间件
  • SalesForce.com 用作后端的客户关系管理 (CRM) 系统

此场景的总结如下(参见图 1):

  1. 用户在移动设备上启动 Worklight 应用程序。
  2. 移动应用程序将用户请求发送到 Worklight 服务器。
  3. Worklight 服务器使用 Cast Iron Adapter 将用户请求传播到 Cast Iron,并发出一条 HTTP GET 请求。
  4. Cast Iron 使用它的内置 SalesForce.com 连接器查询 SalesForce.com,以获得所请求的帐户或联系人信息。
  5. Cast Iron 使用一个基于 HTTP 的 XML 响应回复原始的 Worklight 服务器。
  6. Worklight 服务器使用一个基于 HTTP 的 JSON 响应回复设备。
图 1. 场景概述
场景概述

本文基于 WebSphere Cast Iron Studio V6.1.0.9 和 IBM Worklight V5.0.3(任何版本)。

Cast Iron 假设

对于本文,我们为 Cast Iron 选择了以下假设:

  • Worklight 将通过 HTTP 请求与 Cast Iron 通信。
  • 仅针对此场景,参数将传递到 URL 中。要获得特定帐户的联系人对象,需要将帐户标识符 (accountid) 传递到 Cast Iron。该标识符将是 URI 的一部分,例如 http://castironserver/getContacts?id=accountid。但是,这样做不安全,帐户标识符需要有安全保护(加密或编码)。本文不打算介绍这种安全机制。
  • 因为 Worklight 会自动将 XML 有效负载转换为 JSON 有效负载,所以 Cast Iron 使用基于 HTTP 的 XML 响应回复 Worklight。
  • 如果没有找到任何帐户或联系人,或者 Cast Iron 中出现任何错误,则会将一条 XML 错误消息发送回 Worklight,如下所示。Description 元素中填入了错误来源:
    <Error>
        <Name>Cast Iron Error</Name>
        <Description/>
    </Error>

在文章的 下载 部分中,您会找到用于生成此错误消息的模式 ErrorLog.xsd

Worklight 假设

出于本文的用途,我们选择了以下 Worklight 假设:

  • 为了构建移动应用程序,我们选择创建一个混合应用程序并使用 Dojo 框架(jQuery 或 Sencha 是其他替代选择)。
  • 我们未在移动应用程序中包含任何能提供一种富有吸引力的用户界面的图形设计元素;我们依靠 Dojo 框架默认情况下提供的元素。
  • 我们为 Android® 和 iOS 平台生成并优化了该应用程序,这需要在您的开发环境中安装相应的 SDK。

Cast Iron 配置

这一节将介绍如何创建 Cast Iron 项目来检索 SalesForce.com 帐户和联系人。您将配置两个业务流程:

  • 一个用于检索 SalesForce.com 帐户
  • 另一个用于检索所选帐户的 SalesForce.com 联系人

检索 SalesForce.com 帐户

  1. 打开 Cast Iron Studio 并创建一个新项目。
  2. 创建两个端点:一个用于接收 Worklight 请求,另一个用于 SalesForce.com:
    1. Project 选项卡上,右键单击 Endpoint 并选择 HTTP。保留所有默认参数(选择 Integration Appliance Receives Request)。将端点重命名为 HTTPReceiveRequest。您可能希望为端口号创建一个配置属性 (HttpPortIn),如图 2 所示。
    图 2. 接收 Worklight 请求的 HTTP 端点
    接收 Worklight 请求的 HTTP 端点
  3. Project 选项卡上,右键单击 Endpoint 并选择 Salesforce.com。使用您的 SalesForce.com 帐户信息填写登录部分。再次声明,可为这些值创建配置属性,如图 3 所示。
    图 3. Salesforce.com 端点
    Salesforce.com 端点
  4. 单击此 salesforce.com 端点配置窗格底部的 Test Connection 按钮来测试您的连接。您会获得如图 4 所示的消息。
    图 4. Salesforce.com 端点测试结果
    Salesforce.com 端点测试结果

现在已准备好构建第一个业务流程:

  1. 将已创建的业务流程重命名为 getAccounts
  2. HTTPReceiveRequest 端点拖放到业务流程上,选择 Receive Request 活动。
  3. Configure 检查列表中,填入 /getAccounts 作为 URL 并勾选 Requires a Reply 选项,如图 5 所示。
    图 5. HTTP Receive Request 活动配置
    HTTP Receive Request 活动配置

    现在配置 SalesForce.com 帐户查询。您将在此查询中使用一个 Try 活动激发任何错误。

  4. Try... 活动拖放到 HTTP Receive 活动后。
  5. Try 分支中,拖放 Salesforce.com Endpoint 并选择 Query Objects,如图 6 所示。
    图 6. SalesForce.com Query Objects 活动
    SalesForce.com Query Objects 活动
  6. Configure 检查列表中,填入 SELECT Name, Id FROM Account 作为查询并使用复选框按钮验证该查询(图 7 中用紫色圆圈突出显示)。
    图 7. 查询配置
    查询配置
  7. Map Outputs 检查列表中,使用 Copy 按钮复制 SalesForce.com 结果对象,然后在 SFDCAccounts 中重命名这些对象创建的变量,如图 8 和 9 所示。
    图 8. 获取 SalesForce.com 结果
    获取 SalesForce.com 结果
    图 9. 配置的 Query Objects 活动
    配置的 Query Objects 活动

    检查 Query Objects 活动是否返回了任何内容。如果是,则将 SFDCAccounts XML 文档转换为一个字符串并将它发送回 Worklight。否则,会将一条错误消息发送回 Worklight。

  8. 在 Try 分支内,将 If...Then 活动拖放到 Query Objects 之后。
  9. Left Hand Expression 中配置 “If condition:”。使用椭圆形按钮选择 SFDCAccounts 变量,选择 Id 元素,然后单击 OK(参见图 10)。
    图 10. Left Hand Expression 配置
    Left Hand Expression 配置
  10. 挑选 "!=" 选项作为运算符。最后输入 '' 作为 Right Hand Expression。您会获得如图 11 所示的结果。
    图 11. 配置的 If 活动
    配置的 If 活动
  11. Write XML 活动拖放到 If 分支中。
  12. Configure 检查列表中,选择 SFDCAccounts 变量并单击 OK,如图 12 所示。
    图 12. 选择要序列化的 XML 结构
    选择要序列化的 XML 结构
  13. Map Inputs 检查列表中,选择 SFDCAccounts 变量,并将左侧的 Account 映射到右侧的 Account,如图 13 所示。
    图 13. Map Inputs 配置
    Map Inputs 配置
  14. 在 Map Outputs 检查列表中,使用 Copy 按钮复制序列化结果,将它重命名为 SFDCAccountsString,如图 14 所示。
    图 14. Map Outputs 配置
    Map Outputs 配置

    然后使用一个 Map Variables 活动在一个变量中填充 SalesForce.com 帐户序列化列表。

  15. 仍在 If 分支中,将 Map Variables 活动拖到 Write XML 活动的后面。
  16. 单击 Select Inputs 按钮并选择 SFDCAccountsString 变量,如图 15 所示。
    图 15. Map Variable 活动的输入
    Map Variable 活动的输入
  17. 单击 Select Outputs 按钮,创建一个新字符串变量(使用弹出窗口中的 New 按钮,并将它命名为 outputMessage
  18. 最后,将左侧的 SFDCAccountsString 映射到右侧的 outputMessage,如图 16 所示。
    图 16. Map Variable 活动的最终映射
    Map Variable 活动的最终映射
  19. 最后,将 Send Response 活动拖放到 Try 块的后面(但不在 Try 块中)。配置检查列表已填入了您之前配置的 HTTP Receive Request 活动。
  20. Map Inputs 检查列表中,选择 outputMessage 变量并将它映射到正文,如图 17 所示。
    图 17. 配置要发送回 Worklight 应用程序的结果
    配置要发送回 Worklight 应用程序的结果

    在此阶段,请注意上述活动的 Map Inputs 检查列表上的警告图标。滚动鼠标,您会看到 Cast Iron Studio 生成的警告消息,如图 18 所示。

    图 18. outputMessage 变量的警告消息
    outputMessage 变量的警告消息

    变量 outputMessage 还未在 Try 块外部初始化。这意味着 Cast Iron 不知道此变量的值。一个解决方案是将一个默认值分配给此变量。为此,请转到 Variables 选项卡,选择 outputMessage 变量并分配一个默认值,比如默认的输出消息值

    您几乎已完成了业务流程!要完成该流程,现在需要配置 Else 和 Catch 分支。

    Cast Iron 假设中已解释过,您将基于一个 XML 模式定义生成一个自定义错误消息。

  21. 将 ErrorLog XML Schema 上传到您项目中(本文的 下载 部分中已提供)。
  22. 在 Else 分支中,拖放 Write XML 活动:
    1. 在 Configure 检查列表中,单击 Browse 按钮,基于 ErrorLog 模式创建一个变量,然后使用它作为要序列化的 XML 模式,如图 19 所示。
      图 19. 选择要序列化的 XML 结构
      选择要序列化的 XML 结构
    2. Map Inputs 部分中,在 To Activity 部分中,定义 Name 和 Description 元素的默认值,如图 20 所示,比如定义 Cast Iron Error 作为 Name,定义 No Account found 作为 Description。
      图 20. 分配默认的错误值
      分配默认的错误值
    3. 在 Map Outputs 检查列表中,使用 Copy 按钮复制序列化结果,将它重命名为 ErrorMessage
  23. 仍然在 Else 分支中,将 Map Variables 活动拖放到 Write XML 活动之后。单击 Select Inputs 按钮并选择 ErrorMessage 变量。单击 Select Outputs 按钮并选择 outputMessage 变量。将 ErrorMessage 映射到 outputMessage 变量。
  24. CatchAll 分支中,拖放 Write XML 活动:
    1. Configure 检查列表中,选择之前创建的错误变量(基于 ErrorLog 模式)。
    2. Map Inputs 部分中,单击 Select Inputs 按钮并选择 FaultInfo 变量。为 Name 定义一个默认值,比如 CastIron Error,将 FaultInfo 变量的 message 元素映射到右侧的 description 元素。
    3. Map Outputs 部分中,将 XmlText 变量映射到 outputMessage 变量。

    最后,转到 Orchestration 菜单并选择 Validate 选项,以便使用 Cast Iron Studio 验证您的业务流程。您将得到一条确认消息,表明您的业务流程是有效的。您的业务流程看起来类似于图 21。

    图 21. getAccounts 业务流程
    getAccounts 业务流程

检索 SalesForce.com 联系人

此业务流程将由检索所选帐户的联系人的 SalesForce.com 查询组成。它类似于第一个业务流程,所以您将复制并粘贴 getAccounts 业务流程并修改它。

  1. 复制并粘贴 getAccounts 业务流程。将它重命名为 getContacts
  2. 修改 Receive Request 活动。您将更改 URL 并添加帐户标识符提取,因为此业务流程将从 Worklight 接收 HTTP 请求,比如 http://castironserver/getContacts?id=accountid
    1. 在 Configure 检查列表中,将 URL 更改为 /getContacts
    2. Map Outputs 检查列表中,单击 Select Outputs 按钮,创建一个新字符串变量,并将它命名为 accountId。单击 OK
    3. 拖放 Substring After 功能;将它映射到左侧的 uri 并双击它。在 matchString 参数中填入 id=,如图 22 所示。单击 OK
      图 22. 帐户标识符的提取
      帐户标识符的提取
  3. Substring After 功能映射到右侧的 accountId 变量。
  4. 单击 Query Objects 活动:
    1. 转到 Configure 检查列表,并将查询修改为 SELECT LastName, FirstName, Email FROM Contact WHERE AccountId=$idparam。单击 Validate Query 按钮。
    2. Map Inputs 检查列表中,单击 Select Inputs 按钮并选择 accountId 变量。将它映射到右侧的 idparam 变量,如图 23 所示。
      图 23. 将帐户标识符用于联系人对象查询
      将帐户标识符用于联系人对象查询
    3. Map Outputs 检查列表中,将变量 SFDCAccounts 重命名为 SFDCContacts,将左侧的 Contact 对象映射到右侧的 Contact 对象。
  5. 修改 If 条件分支。在 Left Hand Expression 中,单击椭圆形按钮,选择 SFDCContacts 变量,然后挑选 LastName 字段,如图 24 所示。
    图 24. Left Hand Expression 配置
    Left Hand Expression 配置
  6. 修改 If 条件分支中的 Write XML 活动。
    1. 在 Configure 检查列表中,选择 SFDCContacts 变量并单击 OK
    2. Map Inputs 检查列表中,删除 SFDCAccounts 变量并添加 SFDCContacts 变量。将它映射到右侧的 Contact 变量,如图 25 所示。
      图 25. 获取要序列化的 SalesForce.com Contact 查询结果
      获取要序列化的 SalesForce.com Contact 查询结果
    3. Map Outputs 检查列表中,将变量重名为 SFDCContactsString
  7. 修改 If 条件分支中的 Map Variable 活动,以便将 SFDCContactsString 映射到 outputMessage 变量。
  8. 在 Else 分支中,修改 Write XML 活动。转到 Map Inputs 部分,并将 Description 参数的默认值更改为 No Contact found,如图 26 所示。
    图 26. 没有找到联系人时的自定义错误消息
    没有找到联系人时的自定义错误消息

再次声明,您可能希望 Cast Iron Studio 检查您的业务流程是否有效,像以前一样。您可能希望 Cast Iron Studio 删除您的业务流程的所有未用变量。在 Variables 选项卡中,右键单击 Variables 窗格,并选择 Remove Unused Variable(s) 菜单。

您现在已准备好测试业务流程。您将在 Cast Iron Studio 中本地执行测试,然后将它部署在一个 Cast Iron 服务器上并运行。

在 Cast Iron Studio 上本地测试业务流程

  1. 使用 Verify 选项卡,您将启动您希望测试的业务流程。可以使用 Cast Iron Studio 的 HTTP Post Utility 将 HTTP 请求发送到业务流程。
  2. 要测试 getAccounts 业务流程,可以发送一个请求,比如 http://hostname/getAccounts
  3. 要测试 getContacts 业务流程,则需要在一个请求 URI 中发送一个帐户标识符(您可使用 getAccounts 结果复制一个帐户标识符)。要发送的结果类似于此 URL: http://hostname/getContacts?id=<accountidentifier>.

成功完成本地测试后,您现在可以准备将它部署到 Cast Iron 服务器了。

部署到 Cast Iron 服务器

  1. 在 Cast Iron Studio 中,选择菜单 File > Publish Project,并填入您的 Cast Iron 服务器的主机名、用户名和密码,如图 27 所示。请记住,主机名是管理 IP 地址。
    图 27. 部署在 Cast Iron 服务器上
    部署在 Cast Iron 服务器上
  2. 现在您可以登录到 Cast Iron 服务器 Web 管理控制台。您会看到您的项目已准备启动。

Worklight 配置

构建这个移动应用程序需要 3 个主要步骤:

  1. 设计用户将看到的视图和导航流。这是客户端开发,您将使用 Worklight Studio 的图形编辑器来实现 WYSIWYG。
  2. 创建您在上一节中公开的 Cast Iron 服务的连接。这是服务器端开发,您将使用 Worklight Studio 的适配器功能创建此代码。
  3. 在视图中使用这些服务,以便在用户导航应用程序时动态填充它们。这同样是客户端开发的,需要将一些 Javascript 添加到之前设计的页面中。

您还需要针对 iOS 和 Android 平台优化和生成该应用程序。

设计移动视图和导航流

让我们首先创建移动应用程序项目。图 28 展示了如何着手创建一个基于 Dojo 框架的混合应用程序。

图 28. 创建混合应用程序
创建混合应用程序

该应用程序基于一个典型的导航模板:

  • 一个 “主要” 视图,用于将用户分派各种已实现的功能
  • 一个 “大纲/细节” 视图对。
  1. 让我们首先实现主要视图。使用 Worklight Studio 的图形编辑器,打开主要的 MyCRM.html 文件,确保您处于 “Design 模式”,确保面板已显示。在 “Dojox.mobile” 面板中,将一个 Scrollable view 小部件拖放到您的主页中,如图 29 所示,将它命名为 mainView
    图 29. 创建主要视图
    创建主要视图
  2. 在此视图中,拖放 EdgeToEdgeList 并创建 3 个静态项,方法是右键单击第一项并选择 ListItem / Insert After,如图 30 所示。请注意,在以后您将仅实现链接 “My customers”。
    图 30. 创建主要菜单
    创建主要菜单
  3. 现在是时候实现大纲细节视图了。如图 31 所示,从面板中拖出另一个 ScrollableView,将它放在主要视图之后,将它命名为 accountsView,它包含一个具有标题 My Accounts 的页眉,以及一个链接到前面创建的 “mainView” 的后退按钮。最后,将另一个 EdgeToEdgeList 拖放到此视图中,并将它命名为 accountsList。以后您将使用适配器动态填充此列表。
    图 31. 创建 Accounts 视图
    创建 Accounts 视图
  4. 要实现的最后一个视图显示了链接到 SalesForce.com 中的某个帐户的联系人。切换到您的 HTML 页面的 source 视图,复制并粘贴 accountView,将标题重名为 Contacts,将后退按钮链接到 accountsView,并将列表重名为 contactsList。图 32 展示了应用程序应有的显示外观(请注意左下角的 “Mobile views” 窗口)。
    图 32. 大纲/细节视图的摘要
    大纲/细节视图的摘要
  5. 最后,选择 mainView,右键单击 My accounts 项并选择 List Items / Link to Mobile View(参见图 33)。从下拉框中选择 accountsView,这会确保您可以在单击此项时进入此视图。
    图 33. 将主要视图链接到 Accounts 视图
    将主要视图链接到 Accounts 视图
  6. 在此阶段,您可以测试您的静态应用程序。右键单击 common 文件夹并选择 Run as / Build all and Deploy。打开 http://localhost:8080/console 上的 Worklight 控制台,确保您的应用程序已经部署,单击 Preview as Common Resources 链接。您现在能够在主要菜单视图与联系人视图之间导航了,如图 34 所示。
    图 34. 从控制台测试静态视图
    从控制台测试静态视图

使用一个 Worklight 适配器创建服务器端代码

Worklight 支持您将服务器端代码(访问后端服务)与客户端代码(操作数据以填充视图)分开。服务器端代码可拥有与客户端代码不同的生命周期,只要二者之间的接口合约未更改。所有服务器端代码都通过 Worklight Studio 中的适配器编写。在此场景中,我们使用一个 Cast Iron 适配器调用前面通过 Cast Iron 公开的服务。

  1. 在 Studio 中,选择 File > New > Worklight Adapter 来创建一个新适配器,从 Adapter type 下拉框中选择 Cast Iron,将它命名为 CRMAdapter,如图 35 所示。
    图 35. 创建一个 Cast Iron 适配器
    创建一个 Cast Iron 适配器
  2. 要实现的第一个文件是适配器的 XML 描述符,您可以在其中指定 Cast Iron 的连接,并声明您将实现的两个函数(getAccounts 和 getContacts),如图 36 所示。
    图 36. 配置 Cast Iron 适配器
    配置 Cast Iron 适配器
  3. 现在您已准备好在与适配器一起创建的 Javascript 文件中实现该应用程序。图 37 展示了如何轻松地调用后端服务。请注意,也可以:
    • 混合使用 Javascript 和 Java 代码。
    • 调用多个后端服务并将它们公开为单个服务,以避免在移动应用程序与服务器之间多次往返。
    • 在任何适配器服务调用上添加安全约束。
    图 37. 实现 Cast Iron 远程服务
    实现 Cast Iron 远程服务
  4. 在移动应用程序中使用适配器服务之前,确保已对它们进行测试。在 Project Explorer 视图中,右键单击新创建的适配器,选择第一个 Run as > Deploy Worklight Adapter,然后选择 Run as > Invoke Worklight Procedure。图 38 显示了可用的调用参数。选择 getAccounts 并单击 Run
    图 38. 测试 Cast Iron 远程服务
    测试 Cast Iron 远程服务
  5. 图 39 显示了调查结果。请注意,Cast Iron 返回的 XML 已自动转换为 JSON 格式,这是针对在有限的带宽上传输数据和通过 JavaScript 操作数据而优化的一种方法。在此阶段,需要注意您必须用来填充列表的 JSON 结构。
    图 39. Cast Iron 远程服务调用结果
    Cast Iron 远程服务调用结果

使用远程适配器动态填充视图

您现在已拥有完成应用程序实现所需的所有构建块。一边是移动视图,另一边是适配器服务。

打开主要 HTML 文件,选择 mainView 中的 My customers 项,在 onclick 事件上添加一个 getAccounts Javascript 函数调用,如图 40 所示。

图 40. 在页面加载时调用 getAccounts 服务
在加载页面时调用 getAccounts 服务

现在让我们在 MyCRM.js 文件中实现 “getAccounts” 函数,对前面创建的适配器服务执行一次远程调用。清单 1 展示了如何通过 WL.Client.invokeProcedure 方法调用此适配器,如何实现回调函数来处理结果。

清单 1. 动态填充 Accounts 列表的 Javascript 代码
var busy;

function wlCommonInit(){
    // Common initialization code goes here
    busy = new WL.BusyIndicator('content', {color : '#1D4885'});
    busy.hide();
}

function getAccounts() {
    busy.show();
    var invocationData = {
            adapter: 'CRMAdapter',
            procedure: 'getAccounts',
            parameters: []
    };
    WL.Client.invokeProcedure(invocationData, {
        onSuccess : onGetAccountsSuccess,
        onFailure : onGetAccountsFailed,
        timeout : 30000
    });
}

function onGetAccountsSuccess(response) {
    busy.hide();
    var items = dijit.registry.byId("accountsList");
    items.destroyDescendants();
    if(response.invocationResult.Error) {
        // Functional error returned by CI
        WL.SimpleDialog.show("Error",
         "CRM returned error: " + response.invocationResult.Error.Description,
         [{text : "Close"}]);
    } else {
        var accounts = response.invocationResult.objects.Account;
        if(accounts && accounts.length>0) {
            for(var i=0; i<accounts.length; i++) {
                var account = accounts[i];
                var item = new dojox.mobile.ListItem({
                    moveTo: "contactsView",
                    transition: "slide",
                    label: account.Name
                });
                items.addChild(item);
                item.on("click", dojo.hitch(account, function() 
                 { searchContacts(this); }));
            }
        }
    }
}

function onGetAccountsFailed(response) {
    busy.hide();
    WL.SimpleDialog.show("Error",
            "Failed to connect to back end" + (response.errorMsg ? ": " 
              + response.errorMsg : ""),
            [{text : "Close"}]);
}

当远程适配器调用成功时,会调用 onGetAccountsSuccess 方法。此方法正是循环从后端检索的帐户并动态填充前面创建的 “accountsList” 小部件的适当地方。清单 1 还表明您可以在 JavaScript 中动态创建 Dojo 小部件。请注意,您还在每一项上实现了对 searchContacts 函数的调用,并将当前的帐户 ID 传递给此函数。

searchContacts 函数的实现类似于 getAccounts 函数,但您创建的项无法 单击。清单 2 显示了您将在每一项中显示的联系人数据。

清单 2. 调用 searchContacts 的 Javascript 代码
function searchContacts(account) {
    busy.show();
    var invocationData = {
            adapter: 'CRMAdapter',
            procedure: 'getContacts',
            parameters: [account.Id]
    };
    WL.Client.invokeProcedure(invocationData, {
        onSuccess : onSearchSuccess,
        onFailure : onSearchFailed,
        timeout : 30000
    });
}

function onSearchSuccess(response) {
    busy.hide();
    var items = dijit.registry.byId("contactsList");
    items.destroyDescendants();
    if(response.invocationResult.Error) {
        // Functional error returned by CI
        WL.SimpleDialog.show("Error",
         "CRM returned error: " + response.invocationResult.Error.Description,
         [{text : "Close"}]);
    } else {
        var contacts = response.invocationResult.objects.Contact;
        if(contacts && contacts.length>0) {
            for(var i=0; i<contacts.length; i++) {
                var contact = contacts[i];
                var item = new dojox.mobile.ListItem({
                    label: contact["FirstName"] + ' ' + contact["LastName"] + ' 
                     (' + contact["Email"] + ')'
                });
                items.addChild(item);
            }
        }
    }
}

function onSearchFailed(response) {
    busy.hide();
    var items = dijit.registry.byId("contactsList");
    items.destroyDescendants();
    WL.SimpleDialog.show("Error", "Failed to connect to back end" + 
     (response.errorMsg ? ": " + response.errorMsg : ""), [{text : "Close"}]);
}

针对不同的目标移动操作系统优化应用程序

现在您的应用程序已准备就绪,您必须选择将它们部署到哪些目标环境,以及希望对其中每个环境应用何种优化。Worklight Studio 可帮助您基于(您目前已部署的)一段通用代码优化应用程序,以便您拥有适合执行该应用程序的操作系统和设备的独特体验。出于本演示的用途,您将创建一个 iPhone® 和一个 Android 环境。选择 File > New > Worklight Environment,如图 41 所示,然后实现仅针对 Android 环境的优化。

图 41. 添加 iPhone 和 Android OS
添加 iPhone 和 Android OS

对于 Android 环境,请注意系统后退按钮,人们使用它向后导航到他们的应用程序。这需要对公共目录进行一项细微修改,在 Android 目录中创建了一个专门的实现。如图 42 所示,将一个全局变量和一个 Javascript 函数添加到公共目录中,以存放当前视图。

图 42. 管理导航
管理导航

然后在 Android 目录中,在 MyCRM.js 文件中实现 JavaScript 函数,该函数在每次一个用户单击系统后退按钮时基于当前视图来处理导航。清单 3 显示了实现方法。

清单 3. 针对 Android 优化导航
function wlEnvInit() {
    wlCommonInit();
    // Environment initialization code goes here
    initBackButton();
}

function initBackButton() {
    WL.App.overrideBackButton(backKeyDownFunction);
}

function backKeyDownFunction(){
    switch (currentView.id) {
        case "contactsView":
            currentView.performTransition('accountsView',-1,"slide",null);
            currentView = dijit.registry.byId("accountsView");
            break;
        case "accountsView":
            currentView.performTransition('mainView',-1,"slide",null);
            currentView = dijit.registry.byId("mainView");
            break;
        default:
            navigator.app.exitApp();        
    }
}

此外,您还可以更新 Android MyCRM.css 文件,以隐藏页眉中显示的后退按钮,如清单 4 所示。

清单 4. 隐藏 Android 的后退按钮
/* Hide the Dojo Mobile back button on Android */
.mblToolBarButtonHasLeftArrow {
    display: none;
}

完成之后,确保所有文件都已保存,从 Project Explorer 视图中选择该应用程序,右键单击并选择 Run as > Build all and Deploy。您现在已准备好测试最终的应用程序了。


组装应用程序

首先,可以通过移动浏览器模拟器测试应用程序。打开 Worklight 控制台 (http://localhost:8080/console),单击 AndroidiPhone 并测试应用程序,如图 43 所示。

图 43. 使用移动浏览器模拟器测试最终的应用程序
使用移动浏览器模拟器测试最终的应用程序

此技术对使用内置的可用浏览器调试器来调试所有 Javascript 代码和 CSS 很有用。然后,可生成将部署在每个物理设备上的二进制应用程序。确保您的移动设备与 Worklight Server 位于同一个网络中,比如使用共同的 WIFI 信号。

让我们首先看看 Android 应用程序。因为 Android 开发工具包基于 Java,所以原生 Android 项目已部署在 Eclipse(Android SDK 必须已安装)中一个项目下,这个项目与您的项目或应用程序同名,但加上了 Android 后缀,比如 “SalesMyCRMAndroid”。

通过一个 USB 线将您的物理设备连接到您的机器上。确保您已安装了移动设备的驱动程序,确保您的 Android 设备已启用了 “USB 调试模式”。然后通过右键单击并选择 Run as > Android Application,选择 Eclipse 中创建的 Android 项目。它自动将 apk 二进制文件部署在您的移动设备上,您已准备好测试该应用程序了,如图 44 所示。确保后退按钮支持您在视图之间导航,因为您已在 Android 环境中实现了此部件。

图 44. Android 上的最终应用程序
Android 上的最终应用程序

对于 iPhone 环境,必须使用一个名为 Xcode 的开发工具编译应用程序,该工具仅在 MacOS 上提供。因此,当在 MacOS 环境中运行 Eclipse 时,可以右键单击 iPhone 文件夹并选择 Run as > Xcode project,如图 45 所示。

图 45. 为 iOS 生成应用程序
为 iOS 生成应用程序

生成之后,Xcode Studio 会自动启动,您可以直接使用内置的模拟器来测试应用程序。也可以使用您的 Apple® Provisioning Profile 更新项目设置来生成和签名随后可部署在一个真实设备上的二进制文件(ipa 文件)。图 46 显示了该应用程序在 iPhone 模拟器上的外观。

图 46. 使用 iPhone 模拟器测试应用程序
使用 iPhone 模拟器测试应用程序

图 47 显示了应用程序在部署到 iPhone 上时的外观。可以看到标题中的后退按钮,确保能够在 iPhone 上正确导航。

图 47. iPhone 上的最终应用程序
iPhone 上的最终应用程序

最后,您可以打开 Cast Iron Web Management Console 来监视 Worklight 调用,如图 48 所示。

图 48. Cast Iron Web Management Console
Cast Iron Web Management Console

您还可以深入查看每个业务流程的执行。当启用了日志级调试时,可以看到此业务流程中的每个活动的详细视图,如图 49 所示。

图 49. getContacts 业务流程的详细视图
getContacts 业务流程的详细视图

应用程序的可能扩展

此应用程序的一个更高级版本可添加以下功能:

  • 通知:Worklight 提供了一个统一的通知 API,您可以在服务器端使用它向移动应用程序发送通知。Cast Iron 可订阅 SalesForce.com 中的一个事件,比如对某个帐户或联系人的更改,在 Worklight Server 上调用一个会创建通知消息的 HTTP 适配器,并将它发送给负责该帐户的最终用户。移动应用程序已针对处理此消息进行了增强。
  • 安全:Worklight 提供了一种简单而又强大的方式来控制身份验证和对后端服务的访问。通过实现启动时或按需身份验证,可在参数中使用经过验证的用户的身份来调用 Cast Iron。Cast Iron 在它的查询中考虑到了此信息,以便过滤链接到当前用户的帐户。

结束语

作为 IBM Mobile Foundation 的一部分,IBM Worklight 和 WebSphere Cast Iron 使您能够快速构建和运行连接到您的后端系统的移动应用程序。为了加速开发,Cast Iron 致力于实现简单性,不需要任何代码,只需配置流程。另一方面,Worklight 致力于实现标准(HTML5,开源图形库),这样您就可以重用现有的技能集来构建移动应用程序。Worklight 在客户端与服务器端代码之间提供了明确的分界线。Worklight 服务器充当着移动中间件,可为您的应用程序的移动应用程序管理提供保障。


下载

描述名字大小
代码样例WL-CI-download.zip24368KB
代码样例ErrorLog.xsd1KB

参考资料

学习

获得产品和技术

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=WebSphere, 移动开发
ArticleID=860044
ArticleTitle=将用于访问 SalesForce.com 数据的移动应用程序与 IBM Worklight 和 IBM WebSphere Cast Iron 相集成
publish-date=02282013