为 IBM Lotus Expeditor 创建网络感知应用程序
Lotus Expeditor Client 提供了一种广泛的网络管理框架,可使应用程序具备网络感知功能。它使应用程序能够访问客户机平台的网络状态以及与远端资源的连接性;它也可以将网络状态的变化通知给实现中的应用程序。Lotus Expeditor 网络框架还可以扩展,提供了两个扩展点,应用程序可用这两个扩展点来提供网络故障的定制检测和处理。
本文展示了 Lotus Expeditor Client 的网络功能,并通过一个详细示例介绍了如何让应用程序具网络感知功能。
本文需要您对 Java 以及 Eclipse 插件开发有足够的理解。而且还需要您拥有 Lotus Expeditor 的基础知识,且安装过 Lotus Expeditor Toolkit。关于这些主题的更多信息,可以在本文的 “参考资料” 部分找到。
Lotus Expeditor 的网络感知层提供了一个基本框架以便处理平台范围内的网络错误。它由表 1 中所示的组件组成。
表 1. Lotus Expeditor 的网络感知框架
插件 | 描述 |
---|---|
com.ibm.rcp.offline | 管理客户机的网络状态以及可由客户机及其应用程序访问的远端资源的状态转变。 |
com.ibm.rcp.net.faults | 充当处理本地和远端网络故障的基本框架。提供两个扩展点(处理程序和检测器),可由应用程序扩展。 |
com.ibm.rcp.net.defaults | 提供用来检测和处理某些网络故障的默认实现。 |
com.ibm.rcp.net.status | 检测客户机的网络适配器状态。 |
com.ibm.rcp.net.status.win32 | Microsoft Windows 上的网络状态服务的本地实现。 |
com.ibm.rcp.net.status.linux | Linux 上的网络状态服务的本地实现。 |
Lotus Expeditor 的网络感知功能是双重的。它不仅管理本地网络适配器的连接性,而且还提供了管理已注册的远端资源连接性的机制。
Lotus Expeditor 的网络状态组件可监视客户机的网络适配器的网络连接性。如果网络电缆未插入或者是网络适配器不能连接到网络,那么相应的错误就会发送到网络故障组件。此组件继而通知已注册的应用程序以便它们遇到这个网络错误之前采取相应的操作。此外,Lotus Expeditor 网络服务还可继续监测适配器的网络连接性以及在重获连接性时立即通知已注册的应用程序。
Lotus Expeditor 允许应用程序注册到远端服务器。若任何使用该服务器的应用程序在试图连接此服务器时遇到网络故障,这个应用程序就会通知相应的网络故障组件。此组件之后再通知注册到该服务器的所有应用程序以便它们能够在遇到故障之前就可以采取适当的措施。虽然默认的 Lotus Expeditor 实现并不提供检测服务器何时重新在线的机制,但是可以适当扩展网络故障组件以提供能检测远端资源可用性的监视器。
Lotus Expeditor 的网络感知框架基于及早检测和通知的理念。任何想要利用网络感知功能的应用程序都必须要注册此框架。网络感知框架只检测本地网络故障。它并不自动检测远端网络故障,而是依赖于第一个遇到故障的应用程序宣告故障的存在(我们会在本文稍后的内容加以介绍)。一旦网络感知框架获悉网络故障,它就会将故障分类并在其他应用程序遇到相同的故障之前通知所有其他的侦听程序。这个警告让应用程序能够在故障发生之前即可采取措施,有效消除了用户中断。
Lotus Expeditor 还提供了 Online/Offline 小部件,它显示在 Lotus Expeditor Client 右下角,如图 1 所示。用户可以通过将按钮从 Online 切换成 Offline 来请求断开客户连接。这类计划好的断开让应用程序得以结束它们的网络活动并准备好断开网络。在这种场景中,网络层通知所有的网络侦听程序:离线的请求已发布。每个应用程序随后都能采取适当的步骤以为断开做好准备。应用程序也可以取消对离线的请求,通常的做法是提示用户一个网络任务正在执行,或者为用户提供取消任务和继续离线的选项,或者完全取消离线请求。
图 1. Lotus Expeditor Client 中的 Online/Offline 开关按钮
Lotus Notes V8.0 在 Lotus Expeditor 平台之上构建,是受益于 Lotus Expeditor 的网络感知特性的一种应用程序。它的复制功能使用了此框架以便检测到邮件服务器的连接丢失或者进行到备份服务器的故障转换。Lotus Expeditor 的 Synchronization Manager 也利用了计划好的断开连接场景来提示用户在离线之前先进行同步。
我们创建了一个简单的应用程序,该应用程序可以详尽地展示 Lotus Expeditor 的网络感知特性。它从一个远端服务器检索遍布全球的 IBM 站点的当前时间。通过在应用程序中启用网络感知特性,就能区分网络故障并确定合适的行为。
从本文的 “下载” 部分可以下载此示例应用程序,继而跟随 README.txt 的指导来设置该示例并将此项目导入到 Eclipse 工作区。此示例应用程序称为 com.ibm.rcp.time.client,包含 8 个类,如表 2 所列。
表 2. Time client 类
类 | 描述 |
---|---|
com.ibm.rcp.time.client | |
Activator.java | 控制插件生命周期 |
IConnectionStates.java | 包含连接状态的公共接口 |
TimeBean.java | 负责将时间返回到用户界面 |
com.ibm.rcp.time.client.perspective | |
TimeClientPerspective.java | 当 IBM time client 应用程序打开时所显示的透视 |
TimeClientView.java | time client UI |
com.ibm.rcp.time.client.netaware | |
NetworkConnectivityListener.java | com.ibm.rcp.offline.api.server.INetworkAware 的实现,可侦听到本地网络的连接性的变化 |
ServerConnectivityListener.java | com.ibm.rcp.offline.api.server.INetworkAware 的实现,可侦听到远端服务器的连接性的变化 |
ServerConnectivityMonitor.java | 对 com.ibm.rcp.net.faults.handler 的扩展,可监视远端服务器的连接性 |
随着我们进一步启用网络感知特性,会对 com.ibm.rcp.time.client.netaware 包中的这些类有更加详尽地描述。
我们首先为此客户机的总的连接性丢失启用感知特性。包括计划好的断开以及本地网络的突发断开。
用 Lotus Expeditor 的网络组件注册应用程序的第一个步骤是实现 com.ibm.rcp.offline 插件中的 com.ibm.rcp.offline.api.service.INetworkAware 接口。一旦注册,这个子类就会接收由 Lotus Expeditor 网络组件发送的网络状态转换的通知。
对于这个示例而言,我们关注于四个方法的实现,它们是 disconnected()、reconnected()、goOffline() 和 goOnline()。 有关此类中的其他方法的细节,可以在 Lotus Expeditor Information Center 的参考部分找到。
当网络感知组件检测到客户机突然离线,而不是计划中的断开时,就会调用 disconnected() 方法。而当网络感知组件检测到此客户机已经重获了对网络的连接时,就会调用 reconnected() 方法。当计划好的断开获得了所有注册组件的许可后,就会调用 goOffline() 方法。同样地,一旦计划好的重新连接通过后,就会调用 goOnline() 方法。应用程序不需要为任何的计划断开或重接做准备,所以 goOffline() 方法可以简单地调用 disconnected() 方法,而 goOnline() 方法也可以简单地调用 reconnected() 方法。
应用程序从远端服务器检索遍布全球的各个 IBM 站点的当前时间。通过利用 Lotus Expeditor 的网络感知特性,一旦丢失网络连接,就会通知该应用程序(通过 disconnected() 方法)。这时,这个应用程序反而可以基于系统时钟计算本地时间。但应用程序又如何能够知道何时重新建立连接呢?Lotus Expeditor 网络组件包含了一个系统连接性监测器,可不断地监测网络适配器的状态并在发生状态更改的时候,通知经过注册的组件。这就无需由应用程序监测本地网络或处理网络故障。在再次远程检索时间之前,应用程序只需等待网络连接已重获的通知(通过 reconnected() 方法)。
如果不考虑我们目前没有实现的那些方法,INetworkAware 类与清单 1 中所示的代码极为相似。
清单 1. INetworkAware 类
public class NetworkConnectivityListener implements IConnectionStates, INetworkAware { /** * Called by the offline service when network is no longer available. */ public void disconnected() { //set network state to disconnected TimeBean._networkState = STATE_DISCONNECTED_NETWORK; } /** * Called by the offline service when network is available again. */ public void reconnected() { //set network state to connected TimeBean._networkState = STATE_CONNECTED; } /** * Called by the offline service when it is disconnecting from the network. */ public void goOffline() { disconnected(); } /** * Called by the offline service when it is reconnecting to the network. */ public void goOnline() { reconnected(); } ... } |
这里实现的 disconnected() 方法将 TimeBean.java 中的状态更改为 STATE_DISCONNECTED_NETWORK。通过读取这个标志,time client 就会知道它已经不再连接到网络并选择从系统时钟计算站点时间。同样地,reconnected() 方法会将状态更改为 STATE_CONNECTED,以让客户机知道它已再次连接到网络而且可以从服务器检索时间。
为网络事件实现了侦听程序之后,就需要用 Lotus Expeditor 的离线帮助器注册它以开始接收客户机连接的通知。要实现此目的,可以向之前所创建的类中添加离线服务帮助器的一个实例和一个初始化方法,如清单 2 所示。
清单 2. 添加离线服务帮助器和初始化方法
IOfflineServiceHelper myHelper = null; /** * Initializes the connectivity listener by registering with the offline service. * * @return an instance of this class. */ public INetworkAware init() { //create offline service helper myHelper = IOfflineServiceHelperFactory.INSTANCE.create(this); return this; } |
此后,当应用程序启动时,只需实例化侦听类的一个实例:
INetworkAware networkListener = new NetworkAwareImpl().init();
这可以由 com.ibm.rcp.time.client.Activator.java. 中的 start() 实现。除了注册之外,当应用程序停止时,还需要关闭由侦听类创建的服务。这可以由 com.ibm.rcp.time.client.Activator.java 的 stop() 方法实现:
networkListener.getOfflineServiceHelper().closeOfflineService();
在向此应用程序添加进一步的功能性之前,让我们先试着运行一下。为了从工具箱运行此应用程序,打开在项目的 META-INF 文件夹中的 MANIFEST.MF 文件。在 Overview 附签,单击 Testing 部分的 "Launch Client Services Application" 链接,如图 2 所示。
图 2. “Launch Client Services application” 链接
这会使应用程序在 Lotus Expeditor Client 中启动。输入 Lotus Expeditor Client 密码并选择 Open - IBM Time Client。出现一个视图显示遍布全球的 IBM 站点的当前时间。这些时间都是当前远程检索的。
接下来,使用 Online/Offline 开关按钮将客户机的状态更改为 Offline。单击 Refresh 按钮。注意 IBM 站点时间也已更新,即便您失去了到 Internet 的连接。在后台,Lotus Expeditor 网络框架会通知应用程序有关的连接丢失。此时,之前所实现的 disconnected() 方法会让 time client 感知到网络状态的更改,而此客户机会从系统时钟计算所显示的时间。
重获网络连接之后,就会通知侦听程序,而此 time client 则再次会从 Web 服务器检索时间。这可以通过将 Online/Offline 按钮切换成 Online 实现。
您可以添加对远端资源连接的感知特性来充分利用 Lotus Expeditor 网络框架,从这个远端服务器,应用程序可以检索其时间。出于本例的说明目的,我们假设从服务器检索到的时间更加精确,因而也更加理想。如果主服务器不可用,但客户机尚具有网络连接,就需要故障转换到备用服务器,而不是使用系统时间。这可以通过实现另一个连接性侦听程序并将其关联到服务器上下文来实现。
服务器连接性侦听程序的如下实现与我们为本地网络感知特性所创建的那个侦听程序稍有不同。在这个侦听程序中,不再关注 goOffline() 和 goOnline() 方法。这些方法由网络框架在客户机完全从网络断开(计划好的断开)时调用。由于我们已经在之前的侦听程序实现中处理过这种情况,因此我们无需在此再次处理。
此外,当为一个远端资源注册一个侦听程序时,网络框架会要求您传递过来一个服务器上下文,即代表您所感兴趣的服务器的字符串值。这也需要对 init() 方法进行修改以便能够接受 String 上下文。此服务器侦听程序的实现如清单 3 所示。
清单 3. 实现服务器侦听程序
public class ServerConnectivityListener implements INetworkAware, IConnectionStates { IOfflineServiceHelper myHelper = null; /** * Initializes the connectivity listener by registering with the * offline service. * @param context The server in which the listener is interested. * @return an instance of this class. */ public INetworkAware init(String context) { //create offline service helper myHelper = IOfflineServiceHelperFactory.INSTANCE.create(this, context); return this; } /** * Called by the offline service when the context with which the * listener is registered is no longer available. */ public void disconnected() { //set network state to disconnected TimeBean._networkState = STATE_DISCONNECTED_PRIMARY_SERVER; } /** * Called by the offline service when the context with which the * listener is registered is available. */ public void reconnected() { //set network state to connected TimeBean._networkState = STATE_CONNECTED; } /** * Returns the offline service helper. */ public IOfflineServiceHelper getOfflineServiceHelper() { return myHelper; } ... } |
此外,也需要在 com.ibm.rcp.time.client.Activator.java 的 start() 方法中注册此侦听程序。
serverListener = new
ServerConnectivityListener().init(TimeBean.PRIMARY_SERVER);
当然,也不要忘了在 com.ibm.rcp.time.client.Activator.java 的 stop() 方法中关闭由这个侦听程序创建的离线服务帮助器。
serverListener.getOfflineServiceHelper().closeOfflineService();
现在,当 Lotus Expeditor 的网络感知组件检测到服务器不可用时,它就会调用 disconnected() 方法。在 disconnected() 方法中,可以为 time client 设置网络状态标志以通知它转换到备用服务器。
但,您还是会面临一个问题。在 Lotus Expeditor 中对网络感知的支持并不主动监测远端资源的连接。框架如何知道服务器可用与否或连接丢失以后何时它会再次可用呢?答案很简单:您必须通知它。这可以通过网络感知框架提供的公共 API 加以实现。
网络故障框架提供给开发人员一个 API,此 API 可以分类由应用程序传递给它的网络异常。然后,它通过 handle() 方法将此故障传递给对 com.ibm.rcp.net.faults.handlert 扩展点的所有扩展。每个处理器都会检查此故障,决定它是否是所感兴趣的,如果是,就执行合适的行为。在这种场景中,需要有一个处理程序以便检测与主服务器上下文相关的连接故障并触发 Eclipse Job 来监视远端资源的可用性。但首先,如果丢失了到主服务器的连接,您必须通知该框架。
com.ibm.rcp.time.client.TimeBean.java 类负责连接到服务器和通过 getTimeFromServer() 方法检索时间。此方法会试图打开指向远端服务器的 URL 对象上的一个流。如果异常在这个打开连接的过程中发生,那么就必须将其通过 DetectAndHandle.detectAndHandle() 方法传递到网络框架。detectAndHandle() 方法接受两个参数:所抛出的那个异常以及抛出异常的上下文。在本例中,上下文就是服务器。这就是负责分类所给出异常并将其传递给处理程序扩展的方法。如下所示的到 detectAndHandle() 的调用放置于 TimeBean.java 中的 getTimeFromServer() 方法的捕获块。
DetectAndHandle.detectAndHandle(new ConnectException(e.getMessage()), server);
这些就绪后,当主服务器不可用时,就会通知网络框架。它然后调用用服务器上下文注册的服务器连接性侦听程序中的 disconnected() 方法。随后,应用程序就知道要转换到备用服务器。
通过扩展处理程序扩展点,可以检测作为 ConnectException 的结果进行分类的故障,而且还可以启动 Eclipse Job 来监视远端服务器的可用性,而无需占用应用程序的主线程。
创建处理程序的第一步是实现 com.ibm.rcp.net.faults.Handler 接口,如清单 4 所示。这个接口包含一个方法,称为 handle(),它接受 Fault 对象数组。Lotus Expeditor 提供的 com.ibm.rcp.net.faults 插件包含一系列用来描述各种网络错误的 Fault 对象。我们只关心其中的 ConnectFault,原因是它描述了当主服务器不可用时,对应用程序可见的 ConnectException。每个 Fault 对象都包含一个称为 context 的对象。在 detectAndHandle() 方法中传递给网络框架的 context 对象是主服务器的字符串表示。因此,在 handle() 实现(参见清单 4),需要遍历 Fault 对象数组以查找 String 上下文等于主服务器的 ConnectFault。一旦找到,就表示主服务器不可用,需要立即开始监测连接性。请注意,每次检测到网络故障时,都会调用 com.ibm.rcp.net.faults.handler 扩展点的每个扩展内的 handle() 方法。出于这个原因,就有必要确保只在适当的故障发生时才开启连接性监视器。
清单 4. 实现 handle()
//called by the network component when a fault is detected public void handle(Fault[] faults) { for (int i = 0; i < faults.length; i++) { Fault f = faults[i]; Object context = f.getContext(); if (context != null && f instanceof ConnectFault && f.getContext().toString().equals(TimeBean.PRIMARY_SERVER)) { //start monitor reconnect(context); break; } } } |
当为远端资源创建监视器时,最好的做法是扩展 Eclipse Job 框架。这将让监视器运行在其自身的线程内,防止它占用应用程序的主资源。更多信息,请参看 Eclipse Job 框架。
完成主服务器监视器所需的最后一步是在到远端服务器的连接被恢复时通知 Lotus Expeditor 网络框架。网络感知框架随后会通知所有注册该服务器上下文的侦听程序,包括通过调用 reconnected() 方法已经注册的那些侦听程序。所实现的 reconnected() 方法会将 time client 的网络状态更改为 STATE_CONNECTED 以便让 time client 知道它可以再次从主服务器检索时间。
要向 Eclipse 框架注册处理程序扩展,必须将如下代码添加到此项目的 plugin.xml 文件,其中的 handlerClass 是实现中的类的名称,而 id 是此处理程序的惟一 ID。参看清单 5。
清单 5. 对 plugin.xml 文件的添加
<extension point="com.ibm.rcp.net.faults.handler"> <handler handlerClass="com.ibm.rcp.time.client.netaware.ServerConnectivityMonitor" id="com.ibm.rcp.time.client.handler.1"/> </extension> |
您可以在 com.ibm.rcp.time.client.netaware.ServerConnectivityMonitor.java 查看服务器连接性监视器的完整实现。
在向您介绍了如何修改现有的应用程序以使其可感知网络之后,您应该可以很容易地创建自己的网络感知应用程序。Lotus Expeditor Client 附带的 Lotus Expeditor Toolkit 可让您轻松为网络感知应用程序创建框架。此工具箱有助于您创建具有必要的网络感知依赖项的空白项目,这些依赖项可以在 Lotus Expeditor 环境中部署。
可按如下步骤创建网络感知应用程序。
- 在 Eclipse,选择 File - New - Project。
- 扩展 Client Services 节点,然后选择 Client Services Project。
- 单击 Next。
- 输入项目名,然后单击 Next。
- 在图 3 所示的下一个面板,为正创建的插件指定这个包和 Activator 类的名称,在这些字段中输入如下内容:
- Plug-in ID: MyNetAwareApplication
- Plug-in Version: 1.0.0
- Plug-in Name: MyNetAwareApplication Plug-in
- Activator: com.im.developerworks.netaware.Activator
图 3. 创建 Activator 类
- 单击 Next。
- 在给出的 Target Features 中滚动并选择 Network Layer,如图 4 所示。
图 4. 选择目标特性
- 单击 Finish。
您的应用程序应该会出现在 Eclipse Package Explorer 中并会为网络感知特性配备必要的 Lotus Expeditor 依赖项。
本文带您领略了 Lotus Expeditor Client 的网络框架的细节,描述了如何修改现有的应用程序以为本地和远端网络资源充分利用这些功能。建议您下载和安装此示例并使用它作为指导来帮助您在自己的 Lotus Expeditor 应用程序中启用网络感知特性。
名字 | 大小 | 下载方法 |
---|---|---|
SampleCode.zip | 28KB | HTTP |
学习
- 您可以参阅本文在 developerWorks 全球站点上的 英文原文 。
- 阅读 developerWorks Lotus 文章 “End-to-end integration with pervasive messaging and IBM Lotus Expeditor micro broker”。
- 阅读 developerWorks Lotus 文章 “在 IBM Lotus Expeditor 中构建脱机应用程序”。
- 阅读 developerWorks Lotus 文章 “使用 IBM Lotus Expeditor V6.1 在桌面和移动设备上开发并部署富客户机应用程序”。
- 阅读 developerWorks Lotus 文章 “Migrating Eclipse RCP applications to IBM Lotus Expeditor”。
- 阅读 developerWorks Lotus 文章 “Creating collaborative components for IBM Lotus Expeditor Property Broker”。
- 阅读 developerWorks Lotus 文章 “开发 OSGi 服务作为 IBM Lotus Expeditor 中的 Web 服务”。
- 阅读 developerWorks Lotus 文章 “在 IBM Lotus Expeditor 中构建并部署简单的 Web 服务资源”。
- 阅读 IBM Redbooks 出版物 Building Composite Applications in Lotus Expeditor V6.1 。
- 阅读 developerWorks Lotus Expeditor 页。
- 参考 IBM Lotus Expeditor Information Center。
- 若想了解有关 Eclipse 开发环境的更多信息或下载这个 IDE,请参看 Eclipse Web 站点。
- 了解 Eclipse Job 框架。