当前位置:首页 >> IT/计算机 >>

CH


F O R U M

N O K I A

A Brief Introduction to MIDP Clients for Web Services
Version 1.0; April 1, 2003

Java

Forum.Nokia.com

目录 1 2 简介 ............................................................................................................................................................... 6 背景 ............................................................................................................................................................... 6 2.1 MIDP HTTP 客户端网络...........................................................................................................................6 2.1.1 概述 ................................................................................................................................................6

2.1.2 HTTP 会话管理 .............................................................................................................................7 2.1.3 HTTP 消息体..................................................................................................................................7 2.1.4 SOAP / HTTP 消息体....................................................................................................................7 2.2 2.3 3 Web 服务、 SOAP,以及 WSDL 概述.................................................................................................7 Java、Web 服务,以及 SOAP...............................................................................................................8

Web 服务移动客户端的设计问题 ........................................................................................................... 8 3.1 组网...............................................................................................................................................................8 3.1.1 网络时延 .......................................................................................................................................8

3.1.2 Web 服务接口功能设计及网络时延 ....................................................................................9 3.2 消息样式 .....................................................................................................................................................9 3.2.1 3.2.2 3.3 同步消息 .......................................................................................................................................9 异步消息 .................................................................................................................................... 10

Web 服务的互操作 ...............................................................................................................................10 3.3.1 SOAP 消息样式:RPC/编码与文档/文字的比较............................................................. 10

3.4 4

服务和应用的生命周期....................................................................................................................... 10

翻译器服务.................................................................................................................................................12 4.1 4.2 概述............................................................................................................................................................ 12 JAXRPC 服务器 ........................................................................................................................................ 13 4.2.1 4.2.2 4.3 翻译器的 Java 接口 ................................................................................................................ 13 翻译器服务的实现.................................................................................................................. 14

翻译器服务描述(WSDL)....................................................................................................................... 19

5

翻译器 MIDlet............................................................................................................................................21 5.1 5.2 5.3 概述............................................................................................................................................................ 21 TranslatorMIDlet.java ........................................................................................................................... 21 TranslatorScreen.java .......................................................................................................................... 24

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

2

Forum.Nokia.com

5.3.1

概述 ............................................................................................................................................. 24

5.3.2 SOAP 消息请求/响应 ............................................................................................................... 24 5.4 5.5 5.6 5.7 5.8 6 SettingsScreen.java............................................................................................................................... 32 HttpPoster.java....................................................................................................................................... 34 HttpPosterListener.java....................................................................................................................... 38 ErrorScreen .............................................................................................................................................. 38 Translator.jad ......................................................................................................................................... 39

范例翻译器服务 SOAP 消息....................................................................................................................40 6.1 6.2 getTranslation 请求.............................................................................................................................. 40 getTranslation 响应............................................................................................................................. 40

7

参考文献.....................................................................................................................................................42

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

3

Forum.Nokia.com

修订纪录
2003 年 4 月 1 日 版本 1.0 文档在诺基亚论坛发布

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

4

Forum.Nokia.com

声明 本文档中的信息基于其现有状况,不存在任何保证,包括销售保证、适用某一特殊用途的保证,或从任何建 议、规范或范例中衍生出来的保证。此外,本文档中提供的并非最终信息,在其最终发布前会做较大改动。本 文档仅用作信息通报。 诺基亚公司不承担所有因实施本文档中所表述的信息而产生的相关责任,包括侵犯任何知识产权的责任。诺基 亚公司并不保证或认为使用这些信息不会构成对相应知识产权的侵犯。 诺基亚公司保留不预先通知而随时修改或撤销本文档的权力。 本文档中出现的手机用户界面仅用于演示,不代表任何实际设备。 版权?属于诺基亚公司, 2003 年。 “诺基亚”和“诺基亚以人为本”是诺基亚公司的注册商标。 Java 和所有基于 Java 的标志是 Sun 微系统有限公司的商标或注册商标。 Java 和所有基于 Java 的标志是 Sun 微系统有限公司的商标或注册商标。 授权许可 本授权仅限于因个人应用而下载和打印本说明,除此之外,不存在对其它任何知识产权的授权许可。

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

5

Forum.Nokia.com

Web 服务 MIDP 客户端简介
版本 1.0,2003 年 4 月 1 日

1 简介
下述文档对访问 Web 服务的网络 MIDlets 作了简要介绍。我们假定读者熟悉 Java 编程、熟悉基于 SOAP 的 Web 服务的基本原则,并熟悉 MIDP 编程的基本知识,例如,读者已经阅读过诺基亚论坛的 文章《MIDP 编程简介》[MIDPPROG]。 我们还假定读者熟悉 MIDP 中的 HTTP 网络基础知识,例如,已经阅读过诺基亚论坛的文章《网络 MIDlets 简介》[MIDPNET]和《一个网络 MIDlet 范例:老虎机》[FRUITMAC]。这些文档涉及诸如 HTTP 状态管理、会话管理、安全等方面的主题。本文将不再深入讨论这些主题。

2 背景
2.1 2.1.1 MIDP HTTP 客户端网络 概述

MIDP 1.0 规范 [MIDPSPEC]指出:一个 MIDP 1.0 兼容实现被强制性地至少实现基于 CLDC 通用连接框架 的 HTTP 1.1 [RFC2616]客户端连接。使用 HTTP 1.1 客户端连接意味着,设备发送一个请求,而服务器 发送一个相应的响应。

request HTTP Server reply
图 1:HTTP 客户端请求-响应 如果仅使用 HTTP 客户端连接,这意味着:除了响应某个请求之外,服务器并不能主动发起对设备的 连接。MIDlet HTTP 客户端往往既可以使用 HTTP GET 方法,也可以使用 POST 方法[RFC2616]。 MIDP 2.0 规范指出:必须强制性地既支持 HTTP 又支持 HTTP/S。(在编写本文档时尚没有出现支持 MIDP2.0 的移动电话。)

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

6

Forum.Nokia.com

2.1.2

HTTP 会话管理

HTTP 是一个无状态协议。可以用 HTTP 状态管理(即: cookies 或 URL 重写)实现 HTTP 会话管理。 诺基亚论坛文章《网络 MIDlets 简介》[MIDPNET]和《一个网络 MIDlet 范例:老虎机》[FRUITMAC]详 细讨论了会话管理及安全等方面的主题。 2.1.3 HTTP 消息体

HTTP 请求和响应消息体中发送的信息只是字节流。MIDlet 和 servlet 选择所使用的信息格式类型来对 这些字节进行编码。 2.1.4 SOAP / HTTP 消息体

基于 SOAP 的 Web 服务的各个端点可以交换 SOAP 消息。HTTP 是用来承载 SOAP 消息的默认传输机 制。SOAP 消息中含有 XML 格式化数据。基于 XML 的消息一般选择 UTF-8,或 UTF-16 字符集以及[XML] [UTF-8] [UTF-16]编码规范。 2.2 Web 服务、 SOAP,以及 WSDL 概述 “Web 服务”这一主题指的是应用对应用的通信。某个 Web 服务只是定位于互联网上的一个服务(如 业务逻辑),而我们可以使用标准的互联网协议(如 HTTP)通过可编程接口访问这个服务。 万维网协会(The World Wide Web Consortium,W3C)为 Web 服务作了如下定义[WSARCH]: Web 服务是由一个 URI 所标识、用 XML 定义并描述其公共接口及其绑定的软件系统。 Web 定义服务可以由其他软件系统来发现,然后它们就以其定义所规定的方式,用遵 循各种互联网协议的基于 XML 的消息与其交互。 与基于 XML 的 Web 服务相关的两个重要规范是《Web 服务定义语言》(Web Services Definition Language ,WSDL)和《简单对象访问协议》(Simple Object Access Protocol,SOAP)。WSDL 用于 描述一个被部署的 Web 服务。而 SOAP 则用于定义特定的 Web 服务中整个服务运行期间各端点 (如,客户端和服务器)之间交换的消息的格式。某个 Web 服务可能将自己注册到一个适当的注册 器(如,提供其 WSDL 描述)中,以便某个客户端可以发现它。这些过程被分别称为注册和服务发 现。 关于 Web 服务的详细讨论超出了本文的范围。可以从众多资源中找到更多的信息。W3C 网站, http://www.w3.org 就是良好的入门,你可以从中找到 Web 服务、SOAP、WSDL 等的当前进展和计划 活动[SOAP] [WSDL] [XML]。 你还将发现,表达状态转换(Representational State Transfer,REST)架构样式是试图解决多种类型 的 Web 服务设计问题[REST]的有用方法,不管你是否决定使用 SOAP。

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

7

Forum.Nokia.com

2.3

Java、Web 服务,以及 SOAP Web 服务的整个领域正在迅速演化中。本文试图为一些重要的主题(当我们设计需要访问某个基于 SOAP 的 Web 服务的 MIDlet 时可能遇到这些主题)提供一个基本的背景介绍,尽管相关标准和实现 的某些方面正在演化中。我们将主要考虑某个 MIDP 客户端如何用 SOAP 协议来访问某个基于 XML 的 Web 服务。 撰写本文时,Java?技术团队(Java? technology community)已经为 Java?2 平台上基于 XML 的 RPC 定义了第一个 JavaTM APIs 版本[JAXRPC]。在 JavaTM 2 Platform, Micro Edition 上定义一个可选包的工作 也在开展之中。 当本文撰写时,诸如 WS-I Basic Profile 这样的 Web 服务互操作性的草案定义也在进行中[WSIBP]。 MIDP 1.0 和 MIDP 2.0 规范并没有规定对 XML 或 SOAP 的任何支持。目前希望使用 XML 或 SOAP 的 MIDP 开发伙伴们经常使用第三方类库。这样做的缺点是:每个 MIDlet 都必须包含这些库。这些库的 大小往往达到 25 到 50K(.class 文件尺寸)。这样就使得 MIDlet 应用代码的潜在使用空间变小了。 本文档中给出的 MIDlet 范例使用开放类库开发[KXML] [KSOAP]。本文并不详细讲述这些类库。你也能 方便地找到其他一些针对 J2ME?设备的 XML 和 SOAP 类库,并以类似的方式使用。读者应该对针对 J2ME 的各种有助于支持 XML 处理的不同类库进行评估,并从中选择最合适的。

3 Web 服务移动客户端的设计问题
3.1 3.1.1 组网 网络时延

无线网络的带宽往往比有线宽带互联网低,公共无线网络(如 GPRS)的带宽通常为每秒几十 K。时 延是指从发送一个请求到收到一个响应的时间。如果与固定宽带网络联接相比较,大多数的公共移 动数据网络的时延及其变化往往高很多(以秒为单位度量)。当设计诸如 MIDlets 这样的移动应用时 应该考虑这个因素。 至于 Web 服务的 MIDP 客户端,必须理解 MIDlet 及其 Web 服务之间的消息流,如下所述: ? 消息请求/响应大小 消息大小(最小、典型,以及最大) ? 消息优先级和重要性 许多消息发送方需要知道每个消息是否真正被发送了,是否被发送对象接收了,同时也需 要知道被发回的响应(在某些点)。 某些类型消息的发送方也许并不需要即时收到响应。

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

8

Forum.Nokia.com

某些消息可能具备高于其他消息的优先级。 经常需要重视的是,完成某项单一的任务需要多少次消息交换。完成这类任务的总延时与 “发送消息的数量”和“每一消息的来回延时”的乘积成正比。 某些消息可能需要加密,并且只能在经过认证和授权的端点之间交换。 ? 消息频度 各种不同种类消息的交换频度(很少…经常)? ? 服务客户端类型 该项服务拥有多少不同的潜在客户端?固定客户端和移动客户端各占多少百分比? 对某个应用的消息流和表现性能参数的理解将使你更好地针对最重要的任务来对应用进行优化。 3.1.2 Web 服务接口功能设计及网络时延

某个 Web 服务接口的功能设计本身需要考虑是否有任何高时延的客户端需要使用这项服务。 ? 假定一个移动客户端应用正在查询某个远程“集合”对象。首先它请求该集合中的一个键列表,然 后用这些主键轮回请求远程集合的各个元素。如果该集合中具有 N 个元素,客户端就会请求 N+1 次,这将造成至少(N+1)*(平均时延/请求数)秒的总时延。(另一个问题是:该集合的 大小和内容根据各个请求的不同而变化。) ? 如果某个类似的集合提供一个操作,在一个单一的请求中索取该集合中所有的键和元素,你就 需要考虑该响应消息的最大尺寸,以确保所有的客户端有能力合理地处理这个最大的响应消 息。 ? 如果某个 MIDP 客户端向某个 Web 服务(或几个 Web 服务)发出几个请求来实施一项单一的任 务,这时就需要考虑网络延时问题(还可能需要考虑某些类型的交易处理问题)。往往可以使 用某个服务器端代理进行专门处理,聚集多个网络请求到比较便宜的较高带宽较低时延的固定 网络连接上,而不通过无线连接。 3.2 3.2.1 消息样式 同步消息

一个远程进程调用(remote procedure call,RPC)是一种允许客户端程序在其他使用了网络联接的 系统上执行操作的机制。某个服务器把一个服务定义为一些可被远程客户端调用的操作集合,同时 发布这个服务以便让客户端使用某种适当的机制来发现自己。 RPC 的语法类似于那些用于在客户端的本地进程空间中调用一个方法的机制。一个 RPC 向某个远程服 务器发送请求,并在服务器上执行这个请求,而客户端则等待远程服务器的响应和最终返回的结 果。这就是同步消息的例子。同步消息的优点是:它有助于确保几个连续的请求能以某种要求的顺 序完成。

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

9

Forum.Nokia.com

如果移动应用程序的代码用到了一个 RPC,需要小心的是,不要在 RPC 完成之前由于网络时延而让用 户接口线程阻塞。这样才能使用户接口处于活动状态,并能对用户作出响应。 3.2.2 异步消息

在异步消息的情况下,移动应用程序的代码首先要求发送一条消息。稍后它也许就能收到一条异步 响应。然而,这取决于该设备是否能接受异步消息(如,SMS 或 UDP 数据报),也取决于该 MIDP 设 备是否拥有一个能让远程发送方向其发送消息的已知地址。本文撰写时,还只有一部分 MIDP 实现能 做到这一点。 3.3 Web 服务的互操作 有关 Web 服务交互所用到的基本信息可以在 Web 服务交互性组织(Web Service Interoperability Organization)的网站 www.ws-i.org 中找到,《WS-I 基本协议》(WS-I Basic Profile) [WSIBP]为可 互操作的 Web 服务系统作了定义。 3.3.1 SOAP 消息样式:RPC/编码与文档/文字的比较

这里只对 SOAP 操作样式和消息编码的使用作简要讨论。《WSDL 规范》(WSDL specification) [WSDL]的 3.4 节和 3.5 节对此课题作了详细讲述。 SOAP 操作既使用 RPC 操作,也使用文档样式的操作。RPC 样式通常用于调用远程进程。《SOAP 1.1 规范》[SOAP]定义了一个 RPC 样式的 SOAP 体元素的结构。而文档样式则用于消息。此外,SOAP 体含 有 XML,这点与《SOAP1.1 规范》第 7 章的规定有所不同。 编码指的是,用作对 SOAP 体元素进行解释(或序列化)的规则。一个“被编码的”SOAP 体使用 SOAP encodingStyle 参数来指出某个 SOAP 消息所使用的序列化规则(请参阅《SOAP 规范》第 4 章和第 5 章)。一个“文字”SOAP 体是指在一个已被定义的 XML schema 中规定的编码解释规则。 目前,现有的许多 Web 服务实现默认使用 RPC/编码样式的 SOAP 通信。然而,未来的趋势是使用文 档/文字样式 SOAP 通信(请参阅《WS-I 基本协议草案》[WSIBP])。 注:考虑到行业发展的现状,本文档中给出的范例使用了客户端和服务之间的 RPC/编码样式 SOAP 消息,因为许多平台目前支持这种样式。然而,MIDlet 范例源码在某些特定处指出了需要修改成文 档/文字样式通信。 3.4 服务和应用的生命周期 当一个客户端/服务器系统中有大量的客户端需要访问其服务时,需要考虑该应用的总的生命周期: ? 由哪个(些)组织提供、维护,及升级该客户端和服务?

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

10

Forum.Nokia.com

o

如果客户端和服务器由不同的组织维护,那么当服务改变(被修改、被改名、被撤 销)时怎么做?当用户遇到问题时他可向谁求助?

?

客户端和服务器软件会升级吗? o 客户端软件和服务器软件同步升级还是异步升级?

?

向某项服务添加新功能是否会影响客户端? o o o 最终用户是否需要下载新的应用软件? 用户是否会得到要求其升级客户端软件的通知(如 e-mail,通讯稿等)? 用户是否会收到一条 WAP 推送消息,以便接收向其设备推送的新版本软件?

如果移动服务用户的数量较少,就比较容易应付这些挑战。当用户数和设备数增加时,就需要预先 准备好应对方案,以便某个 MIDlet 及/或 Web 服务在其设计阶段就考虑到某些重要问题。 各种 Web 服务目前所面临的问题主要关于如何定义、部署、发现,以及使用服务,或者关于它们之 间的互操作。但是,许多问题及其细节还是传统意义上的软件生命周期的一部分。其中包括:为使 用某些特定的 Web 服务接口而定义详细的“用例”和消息参数,定义某个使用接口操作的正确顺序, 定义如何解释格式化的数据,以及定义如何维护和升级系统。

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

11

Forum.Nokia.com

4 翻译器服务
4.1 概述 许多企业向其员工提供可以从某个移动应用(e-mai、信息搜索、公司新闻等)访问的各种服务。这 里用到的范例是某家公司向其频繁出差的移动员工提供的一个简单的文本翻译服务。这样的服务还 可以用其他类型的查询服务(如搜索、辞典查词、词库)来扩展。为了使我们的范例尽可能简单, 这里只用到了一种查询类型。 这项服务既可以由企业本身提供,也可以由合适的服务供应商提供。

getTranslation( inputLocale, outputLocale, inputText)

Translator MIDlet
getTranslationResponse( outputText)

TranslatorService

MIDP Device

Web Service Server

SOAP/HTTP

图 2:翻译器服务

该应用由一个 MIDlet 客户端和一个 Web 服务服务器组成,如图 2 所示。 翻译器 MIDlet 运行在一个支持 MIDP 的电话上。它提供了一个简单的用户界面,用于输入文本、选择 需要的翻译方式(如,英语到法语),并向 Web 服务发送 SOAP 消息请求(用 HTTP 作传输)。Web 服务返回一个 SOAP 响应,其中既可以包含一个 SOAP Fault(SOAP 出错,当发生错误时),也可以包 含被翻译的输出文本,如图 3 所示。

图 3:TranslatorMIDlet 用户界面

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

12

Forum.Nokia.com

4.2

JAXRPC 服务器 一个基于 JAXRPC 的简单翻译器服务是用 Sun 公司的 Java? Web 服务开发商包(Java? Web Services Developer Pack,JWSDP)[JWSDP]实现的。如图 4 所示,可以用 JWSDP 的 HTML 接口检查已部署的范 例服务,从而可以看到该项服务的一些重要属性。 针对该项服务的 XML 名字空间是 http://foo.bar/wsd/translator/1.0/wsdl/TranslatorService。实际部署 这项服务的组织可以将其改变成更合适的 URN 或 URL。(主机“foo.ba”是想象的占位符。)针对所部 署服务的 XML 名字空间和 URL 指出了该项服务的版本信息(即:1.0),因为我们假定某些 Web 服 务随着时间的推进将会升级,而客户端需要有一种方法来确定它们正在使用的是哪一个版本。

图 4:JWSDP JAXRPC TranslatorService 的 HTML 接口 4.2.1 翻译器的 Java 接口

JWSDP 允许人们从一个诸如接口定义这样的 Java 组件来生成一个基于 JAXRPC 的 Web 服务。翻译器 服务的基本定义由下面的方法来定义。JWSDP 使用这个接口定义来生成该服务的 WSDL 描述。 package example.translator; import java.rmi.Remote; import java.rmi.RemoteException; // Translator service interface // // The translation of input text is defined in terms // of input and output 'locale' language options. // The language options are strings that follow the // IETF RFC 3066 'Tags for the Identification of // Languages' (http://www.ietf.org/rfc/rfc3066.txt). public interface Translator extends Remote { // Translate a text string from one language to another // (from inputLocale to outputLocale).

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

13

Forum.Nokia.com

public String getTranslation(String inputLocale, String outputLocale, String inputText) throws RemoteException; // Return an array of strings that indicates the service's // support for translation from one source input language // into another. // For example: { "en: de, es, fr, it, pt", "de: fr, en", ... } // (Ideally information like this should have been defined // in the service description itself.) public String[] getTranslationOptions() throws RemoteException; } 4.2.2 翻译器服务的实现

这里提供了一个简单的翻译器服务实现,以便测试。 注意:该服务中的 getTranslationOptions 方法目前并不被这个 MIDlet 所用。可以修改该 MIDlet 使其向该项服务请求一个针对所支持的语言的更新列表。用这种方式就可以对该服务进行升 级使其能支持新的语种,而不需要改变所部署的客户端。 package example.translator; import java.rmi.RemoteException; import java.util.Locale; import java.util.Properties; public class TranslatorService implements Translator { // The language options (i.e. the inputLocale and outputLocale) // are strings should that follow the IETF RFC 3066 'Tags for the // Identification of Languages'. Only simple language tags like // "en" and "pt" are currently used. private final static String[] locales = { "de", "en", "es", "fr", "it", "pt" }; private final static int DE = 0; private final static int EN = 1; private final static int ES = 2; private final static int FR = 3; private final static int IT = 4; private final static int PT = 5; private String[] getOutputLocales(String inputLocale)

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

14

Forum.Nokia.com

throws RemoteException { // The service's options for translating text from one language // to another may depend on the input language. String[] deTranslationOptions = { locales[EN], locales[FR] }; String[] enTranslationOptions = { locales[ES], locales[DE], locales[FR], locales[IT], locales[PT] }; String[] esTranslationOptions = { locales[EN] }; String[] frTranslationOptions = { locales[DE], locales[EN] }; String[] itTranslationOptions = { locales[EN] }; String[] ptTranslationOptions = { locales[EN] }; if (inputLocale.startsWith(locales[DE])) { return deTranslationOptions; } else if (inputLocale.startsWith(locales[EN])) { return enTranslationOptions; } else if (inputLocale.startsWith(locales[ES])) { return esTranslationOptions; } else if (inputLocale.startsWith(locales[FR])) { return frTranslationOptions; } else if (inputLocale.startsWith(locales[IT])) { return itTranslationOptions; } else if (inputLocale.startsWith(locales[PT])) { return ptTranslationOptions; } else { String msg = errorString("Translation not supported for " + '"' + inputLocale + '"'); throw new RemoteException(msg); } } private boolean isTranslationSupported(String inputLocale, String outputLocale) throws RemoteException { String[] supportedOutputLocales = getOutputLocales(inputLocale); int i; for (i = 0; i < supportedOutputLocales.length; i++) { if (supportedOutputLocales[i].startsWith(

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

15

Forum.Nokia.com

outputLocale.substring(0, 1))) { break; } } if (i == supportedOutputLocales.length) { return false; } else { return true; } } public String getTranslation(String inputLocale, String outputLocale, String inputText) throws RemoteException { if (isTranslationSupported(inputLocale, outputLocale)) { // Note: A real translation service should be used // instead of the simple dummy 'test' implementation below. return dummyGetTranslation(inputLocale, outputLocale, inputText); } else { String msg = errorString("Translation not supported from " + '"' + inputLocale + '"' + " to " + '"' + outputLocale + '"'); throw new RemoteException(msg); } } // An overly simplified implementation of a translation service. // It only translates a small pre-defined set of phrases. private String dummyGetTranslation(String inputLocale, String outputLocale, String inputText) throws RemoteException { // Each row contains a phrase translated in the // following order: DE, EN, ES, FR, IT, PT String[][] phrases = { { "katze", "cat", "gato", "chat", "gatto", "gato" }, { "hallo", "hello", "hola", "bonjour", "ciao", "olá"}, { "auf wiedersehen", "goodbye",

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

16

Forum.Nokia.com

"adiós", "au revoir", "arrivederci", "adeus" }, { "Wo ist der n?chste Bahnhof, bitte?", "Where is the nearest train station, please?", "?Dónde está la estación de tren más cercana, por favor?", "Où est la station de train la plus proche, s'il vous "Dovè la stazione ferroviaria piú vicina, per favore?", "Onde fica a esta??o de comboio mais próxima, por favor?" }, { "Der schnelle braune Fuchs springt über den faulen Hund.", "The quick brown fox jumps over the lazy dog.", "El rápido zorro café salta sobre el perro perezoso.", "Le renard brun rapide saute par-dessus le chien paresseux.", "La svelta volpe marrone salta sopra il cane pigro.", "A rápida raposa castanha salta sobre o c?o pregui?oso." } }; // Locale is used to convert inputText to lower case String country = inputLocale.substring(0, 2); String language; if (inputLocale.length() >= 5) { language = inputLocale.substring(3, 5); } else { language = country.toUpperCase(); } Locale lc = new Locale(country, language); // Get the appropriate output locale index into the phrase table int inputLocaleIndex = EN; for (int i = 0; i < locales.length; i++) { if (locales[i].equals(inputLocale)) { inputLocaleIndex = i; break; } } int outputLocaleIndex = EN; for (int i = 0; i < locales.length; i++) { if (locales[i].equals(outputLocale)) { outputLocaleIndex = i; break;

pla?t?",

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

17

Forum.Nokia.com

} } // If the inputText is found in the phrase table, // return an appropriate translation. for (int phrase = 0; phrase < phrases.length; phrase++) { String lcInputText = inputText.toLowerCase(lc); String nextPhrase = phrases[phrase][inputLocaleIndex]; if (nextPhrase.equals(inputText) || nextPhrase.toLowerCase().equals(lcInputText)) { return phrases[phrase][outputLocaleIndex]; } } // By default, no match was found. String msg = errorString("No translation was found"); throw new RemoteException(msg); } private static String errorString(String message) { return "TranslationServiceError: '" + message+ "'"; } // Note: the MIDlet doesn't currently use either method below // A client could use this method, to find out the list of // supported translations dynamically. // Options for translating from an input locale to an output locale. // Each row is a property like string, e.g. "en: de, es, fr, it, pt" public String[] getTranslationOptions() throws RemoteException { String[] options = new String[locales.length]; for (int i = 0; i < locales.length; i++) { options[i] = locales[i] + ": "; String[] outLocales = getOutputLocales(locales[i]); for (int j = 0; j < outLocales.length; j++) { options[i] += outLocales[j]; if (j < (outLocales.length - 1)) { options[i] += ", "; } } } return options; } }

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

18

Forum.Nokia.com

4.3

翻译器服务描述(WSDL) 下述 WSDL 描述由 JWSDP 自动生成。默认地,JWSDP 从一个 Java 接口定义生成一个 RPC/编码 Web 服务。 <?xml version="1.0" encoding="UTF-8"?> <definitions xmlns=http://schemas.xmlsoap.org/wsdl/ xmlns:tns=http://foo.bar/wsd/translator/1.0/wsdl/TranslatorService xmlns:xsd=http://www.w3.org/2001/XMLSchema xmlns:soap=http://schemas.xmlsoap.org/wsdl/soap/ name="TranslatorService" targetNamespace="http://foo.bar/wsd/translator/1.0/wsdl/TranslatorServic e"> <types/> <message name="Translator_getTranslation"> <part name="String_1" type="xsd:string"/> <part name="String_2" type="xsd:string"/> <part name="String_3" type="xsd:string"/> </message> <message name="Translator_getTranslationResponse"> <part name="result" type="xsd:string"/> </message> <message name="Translator_getVersion"/> <message name="Translator_getVersionResponse"> <part name="result" type="xsd:string"/> </message> <message name="Translator_getTranslationOptions"/> <message name="Translator_getTranslationOptionsResponse"> <part name="result" type="xsd:string"/> </message> <portType name="Translator"> <operation name="getTranslation" parameterOrder="String_1 String_2 String_3"> <input message="tns:Translator_getTranslation"/> <output message="tns:Translator_getTranslationResponse"/> </operation> <operation name="getVersion" parameterOrder=""> <input message="tns:Translator_getVersion"/> <output message="tns:Translator_getVersionResponse"/> </operation> <operation name="getTranslationOptions" parameterOrder=""> <input message="tns:Translator_getTranslationOptions"/> <output message="tns:Translator_getTranslationOptionsResponse"/> </operation> </portType> <binding name="TranslatorBinding" type="tns:Translator"> <operation name="getTranslation"> <input> <soap:body encodingStyle=http://schemas.xmlsoap.org/soap/encoding/ use="encoded" namespace="http://foo.bar/wsd/translator/1.0/wsdl/TranslatorService"/> </input> <output>

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

19

Forum.Nokia.com

<soap:body encodingStyle=http://schemas.xmlsoap.org/soap/encoding/ use="encoded" namespace="http://foo.bar/wsd/translator/1.0/wsdl/TranslatorService"/> </output> <soap:operation soapAction=""/> </operation> <operation name="getVersion"> <input> <soap:body encodingStyle=http://schemas.xmlsoap.org/soap/encoding/ use="encoded" namespace="http://foo.bar/wsd/translator/1.0/wsdl/TranslatorService"/> </input> <output> <soap:body encodingStyle=http://schemas.xmlsoap.org/soap/encoding/ use="encoded" namespace="http://foo.bar/wsd/translator/1.0/wsdl/TranslatorService"/> </output> <soap:operation soapAction=""/> </operation> <operation name="getTranslationOptions"> <input> <soap:body encodingStyle=http://schemas.xmlsoap.org/soap/encoding/ use="encoded" namespace="http://foo.bar/wsd/translator/1.0/wsdl/TranslatorService"/> </input> <output> <soap:body encodingStyle=http://schemas.xmlsoap.org/soap/encoding/ use="encoded" namespace="http://foo.bar/wsd/translator/1.0/wsdl/TranslatorService"/> </output> <soap:operation soapAction=""/></operation> <soap:binding transport=http://schemas.xmlsoap.org/soap/http style="rpc"/></binding> <service name="TranslatorService"> <port name="TranslatorPort" binding="tns:TranslatorBinding"> <soap:address xmlns:wsdl=http://schemas.xmlsoap.org/wsdl/ location="http://myhost:8080/translator/1.0/TranslatorService"/> </port> </service> </definitions>

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

20

Forum.Nokia.com

5
5.1

翻译器 MIDlet
概述 图 5 给出了 TranslatorMIDlet 的类图

Http Poster
creates

calls back

Http PosterListener
calls

Translator MIDlet

creates UI state change requests creates

Translator Screen

Error Screen

UI state change requests

Settings Screen

图 5:MIDlet 类图 TranslatorMIDlet 首先创建一个 HttpPoster,向其传递 Web 服务的 URL。除此之外不存在其他的“服务 发现”步骤。然后 TranslatorMIDlet 再创建自己的屏幕(TranslatorScreen 和 SettingsScreen)并向它 们传递一个用于屏幕 UI 回调的对其自身的引用。 当 TranslatorScreen 请求一个 HttpPoster 对象向 Web 服务发送一个请求时,它向 HttpPoster 传递一 个对其自身作为 HttpPosterListener 的引用,以便当该请求完成时让 HttpPoster 用作回调。 由 于 HttpPoster 见 到 的 不 是 TranslatorScreen 而 是 HttpPosterListener , 它 并 不 依 赖 TranslatorScreen。HttpPoster 加 HttpPosterListener 的组合也可以被其他类使用。在这个简单的范例 中,这种功能并不是必需的,但在更为复杂的 MIDlets 中却很有用,在那种情况下,可以有一个以上 的屏幕向 servlet 发送请求。 5.2 TranslatorMIDlet.java TranslatorMIDlet 类非常简单:它仅仅处理 MIDlet 状态模型回调,而让 UI 保持自身的屏幕。它首先 使用一个基于报警的闪烁屏幕。在闪烁屏幕显示并消失之后,第一个出现的屏幕显示就是 TranslatorScreen。 import javax.microedition.midlet.*; import javax.microedition.lcdui.*; import java.io.IOException; public class TranslatorMIDlet extends MIDlet

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

21

Forum.Nokia.com

{ private final Image logo; private final TranslatorScreen translatorScreen; private final SettingsScreen settingsScreen; private HttpPoster httpPoster = null; public TranslatorMIDlet() { translatorScreen = new TranslatorScreen(this); settingsScreen = new SettingsScreen(this); logo = makeImage("/logo.png"); ErrorScreen.init(logo, Display.getDisplay(this)); } HttpPoster getHttpPoster() { if ((httpPoster == null) || httpPoster.isAborting()) { // This example assumes that both the client + // server always both use UTF-8. httpPoster = new HttpPoster(getAppProperty("TranslatorService-URL")); } return httpPoster; } public void startApp() { Displayable current = Display.getDisplay(this).getCurrent(); if (current == null) { // first time we've been called String text = getAppProperty("MIDlet-Name") + "\n" + getAppProperty("MIDlet-Vendor"); Alert splashScreen = new Alert(null, text, logo, AlertType.INFO); splashScreen.setTimeout(3000); // display splash screen, then request screen Display.getDisplay(this).setCurrent(splashScreen, translatorScreen); } else { Display.getDisplay(this).setCurrent(current); } }

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

22

Forum.Nokia.com

public void pauseApp() { } public void destroyApp(boolean unconditional) { } static Image makeImage(String filename) { Image image = null; try { image = Image.createImage(filename); } catch (Exception e) { } return image; }

// On the exit command, cleanup and notify that // the MIDlet has been destroyed. private void quit() { if (httpPoster != null) { httpPoster.abort(); } destroyApp(false); notifyDestroyed(); } // Screen callbacks void translatorScreenExit() { quit(); } void translatorScreenError(String errorMessage) { ErrorScreen.showError(errorMessage, translatorScreen); } void translatorScreenSettings() { Display.getDisplay(this).setCurrent(settingsScreen); }

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

23

Forum.Nokia.com

void translatorScreenAbortHttpPoster() { if ((httpPoster != null) && !httpPoster.isAborting()) { // Warning: this kills all pending requests httpPoster.abort(); } // TranslatorScreen remains displayed } void settingsScreenBack() { Display.getDisplay(this).setCurrent(translatorScreen); } void settingsScreenSave(String inputLocale, String outputLocale) { translatorScreen.setLocales(inputLocale, outputLocale); Display.getDisplay(this).setCurrent(translatorScreen); } } 5.3 5.3.1 TranslatorScreen.java 概述

这个类提供了该 MIDlet 的用户界面主屏幕。它使用了 MIDP 的高级用户界面:一个用于输入的 TextField 及一个用于输出的 StringItem。当 inputTextField 项中的值变化时,其值被保 存到纪录存储区中(但并没有保存当前翻译选项)。这一屏幕提供几种命令:Translate(翻译)、 Cancel(删除)、Settings(设置),以及 Quit(退出)。 向 Web 服务实际发送 HTTP 请求是通过调用 HttpPoster 实现的。当收到 HTTP 响应时,HttpPoster 将 回调 HttpPosterListener 的 receiveHttpResponse 方法或 handleHttpError 方法。如果用 Cancel(删除)命令来删除一个正在执行的翻译请求,将导致当前由 HttpPoster 进行排队的所有等待 的请求被撤除。调用 Cancel 之后,将创建 HttpPoster 的一个新实例。 5.3.2 SOAP 消息请求/响应

当发送一条 SOAP 消息时,使用 kSOAP 库来为 getTranslation 操作创建 SOAP 封装和一个代表该 Web 服务的 RPC。然后,getTranslation 操作被序列化为 XML,并被送进队列以便用 HttpPoster 发送。 虽然本范例使用了一个 RPC/编码请求,但使用文档/文字请求的唯一不同点是针对该请求所创建的 XML,情况与处理 SOAP 响应类似。

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

24

Forum.Nokia.com

import java.io.*; import java.util.*; import javax.microedition.lcdui.*; import javax.microedition.io.*; import javax.microedition.rms.*; import import import import org.ksoap.*; org.kxml.*; org.kxml.io.*; org.kxml.parser.*;

class TranslatorScreen extends Form implements Runnable, CommandListener, HttpPosterListener { private final static String CHARSET = "UTF-8"; private final static String CONTENT_TYPE = "text/xml; charset=\"" + CHARSET + "\""; private final static int TICK_TIME_MILLIS = 300; private final static int TEXT_RECORD = 1; private private private private private private private private private private final final final final final final final final final final TranslatorMIDlet midlet; Command exitCommand; Command translateCommand; Command settingsCommand; Command cancelCommand; ImageItem activityIndicator; Image active0; Image active1; TextField inputTextField; StringItem outputStringItem;

private String inputLocale = SettingsScreen.DEFAULT_INPUT_LOCALE; private String outputLocale = SettingsScreen.DEFAULT_OUTPUT_LOCALE; private volatile boolean aborting = false; private volatile boolean doAnimation = false; private Thread animationThread = null; private int progressCount = 0; TranslatorScreen(TranslatorMIDlet midlet) { super(null); this.setTitle(titleString()); this.midlet = midlet; // Initialize progress meter active0 = TranslatorMIDlet.makeImage("/active0.png"); active1 = TranslatorMIDlet.makeImage("/active1.png"); int anchor = (ImageItem.LAYOUT_LEFT | ImageItem.LAYOUT_NEWLINE_AFTER); activityIndicator = new ImageItem("Translating",

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

25

Forum.Nokia.com

active0, anchor, ""); // TextField for entering Input inputTextField = new TextField("Input text", "", // default input text 128, TextField.ANY); append(inputTextField); // StringItem for translated Output inputTextField outputStringItem = new StringItem("", ""); append(outputStringItem); // Screen commands exitCommand = new Command("Exit", Command.EXIT, 1); settingsCommand = new Command("Settings", Command.SCREEN, 1); translateCommand = new Command("Translate", Command.SCREEN, 2); cancelCommand = new Command("Cancel", Command.STOP, 2); addCommand(translateCommand); addCommand(settingsCommand); addCommand(exitCommand); setCommandListener(this); } private String titleString() { return inputLocale + " to " + outputLocale + " Translator"; } void setLocales(String inputLocale, String outputLocale) { this.inputLocale = inputLocale; this.outputLocale = outputLocale; clearTranslation(); // update screen's title setTitle(titleString()); } private void clearTranslation() { // clear old translation text outputStringItem.setLabel(""); outputStringItem.setText(""); } // Runnable: this method is used by our thread public void run() { while ((Thread.currentThread() == animationThread) && !aborting)

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

26

Forum.Nokia.com

{ if (doAnimation) { Image image = ((progressCount % 2) == 0) ? active0 : active1; activityIndicator.setImage(image); progressCount++; } try { synchronized (this) { wait(TICK_TIME_MILLIS); } } catch (InterruptedException e) { // continue running } } } public void commandAction(Command command, Displayable d) { if (command == exitCommand) { midlet.translatorScreenExit(); } else if (command == translateCommand) { clearTranslation(); // start animation startActivityIndicator(); // queue request for sending try { queueRequestGetTranslate(); } catch (UnsupportedEncodingException e) { stopActivityIndicator(); midlet.translatorScreenError(e.toString()); } catch (IOException e) { stopActivityIndicator(); midlet.translatorScreenError(e.toString()); } } else if (command == cancelCommand) {

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

27

Forum.Nokia.com

stopActivityIndicator(); // Warning: this aborts all send requests that are queued ! midlet.translatorScreenAbortHttpPoster(); } else if (command == settingsCommand) { midlet.translatorScreenSettings(); } } private byte[] getTranslationSOAPRequest(String inputLocale, String outputLocale, String inputText) throws UnsupportedEncodingException { // You could use an appropriate SOAP helper classes to construct // the request message in approximately the following manner: // String methodNamespace = // "http://foo.bar/wsd/translator/1.0/wsdl/TranslatorService"; // String method = "getTranslation"; // SoapObject soapRequest = // new SoapObject(methodNamespace, method); // soapRequest.addProperty("String_1", inputLocale); // soapRequest.addProperty("String_2", outputLocale); // soapRequest.addProperty("String_3", inputText); // ... convert to UTF-8 bytes, prepend XML prolog, etc. ... // // Assuming you know what the 'canned' request looks like, // the approach below is a simpler way to construct and encode // trivial UTF-8 (or UTF-16) SOAP requests. String soapMessage = "<?xml version=\"1.0\" encoding=\"" + CHARSET + "\"?>\n" + "<SOAP-ENV:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " + "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " + "xmlns:SOAPENC=\"http://schemas.xmlsoap.org/soap/encoding/\" " + "xmlns:SOAPENV=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" + "<SOAP-ENV:Body " + "SOAPENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n" + "<getTranslation " + "xmlns=\"http://foo.bar/wsd/translator/1.0/wsdl/TranslatorService\" " + "id=\"o0\" " + "SOAP-ENC:root=\"1\">\n" + "<String_1 xmlns=\"\" xsi:type=\"xsd:string\">" + inputLocale + "</String_1>\n" + "<String_2 xmlns=\"\" xsi:type=\"xsd:string\">" + outputLocale + "</String_2>\n" + "<String_3 xmlns=\"\" xsi:type=\"xsd:string\">" + inputText + "</String_3>\n" + "</getTranslation>\n" + "</SOAP-ENV:Body>\n" +

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

28

Forum.Nokia.com

"</SOAP-ENV:Envelope>\n"; return soapMessage.getBytes(CHARSET); } private void queueRequestGetTranslate() throws IOException, UnsupportedEncodingException { byte[] bytes = getTranslationSOAPRequest(inputLocale, outputLocale, inputTextField.getString()); Hashtable httpRequestProperties = new Hashtable(); httpRequestProperties.put("Content-Type", CONTENT_TYPE); httpRequestProperties.put("Content-Length", Integer.toString(bytes.length)); // (Set SOAPAction here if needed.) midlet.getHttpPoster().sendHttpRequest(bytes, httpRequestProperties, this); } // // // // // // // // // // // // // // // // // // // // // // // // Note: If you can't test the MIDlet with the matching JWSDP 1.1 JAX-RPC based web service sample implementation that was provided, then by making some minor changes to the code you might be able to modify it to work with an alternate similar web service. At the time of writing, http://www.xmethods.net seems to provide a similar service, the source code changes might look like this: 1) Change .jad's TranslatorService-URL: http://services.xmethods.net:80/perl/soaplite.cgi 2) Set SOAP-Action property in the HTTP header: httpRequestProperties.put("SOAPAction", "urn:xmethodsBabelFish#BabelFish"); 3) Modify the SOAP request appropriately (method getTranslationSOAPRequest): method namespace: "urn:xmethodsBabelFish" method: "BabelFish" parameter 1 name: "translationmode" parameter 1 value: (inputLocale + "_" + outputLocale) parameter 2 name: "sourcedata" parameter 2 value: inputText 4) Modify method handleHttpResponse to handle "BabelFishResponse" instead of "getTranslationResponse" Etc. ...

// add an animated activityIndicator to the Form private void startActivityIndicator() { removeCommand(translateCommand); addCommand(cancelCommand); if (size() == 2) {

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

29

Forum.Nokia.com

// add indicator at top of Form insert(0, activityIndicator); } // start animation aborting = false; doAnimation = true; animationThread = new Thread(this); animationThread.start(); } // Stop the activityIndicator's animation and remove from Form private void stopActivityIndicator() { // stop animation aborting = true; doAnimation = false; if (size() == 3) { // remove indicator from top of Form delete(0); } removeCommand(cancelCommand); addCommand(translateCommand); } // HttpPosterListener methods public void receiveHttpResponse(byte[] bytes) { stopActivityIndicator(); SoapEnvelope resultEnvelope = new SoapEnvelope(); try { ByteArrayInputStream bis = new ByteArrayInputStream(bytes); Reader reader = new InputStreamReader(bis); XmlParser parser = new XmlParser(reader); resultEnvelope.parse(parser); } catch (IOException e) { midlet.translatorScreenError("Response Parsing Error: " + e.toString()); } Object body = resultEnvelope.getBody(); if (body instanceof SoapFault) { SoapFault fault = (SoapFault) body; // The SoapFault fault string may be verbose. // It contains the 'TranslationService error' message.

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

30

Forum.Nokia.com

midlet.translatorScreenError(fault.toString()); } else { // (Note: You normally parse the XML formatted response here // as needed: either the 'Document/Literal' or 'RPC/Encoded // SOAP response depending on your web service. // The simpler approach below was used because // TranslationService's response is so simple, // something like this: // <env:Envelope ... ><env:Body> // <ans1:getTranslationResponse // xmlns:ans1="http://foo.bar/wsd/translator/1.0/wsdl/TranslatorService"> // <result xsi:type="xsd:string">resultStringGoesHere</result> // </ans1:getTranslationResponse> // </env:Body></env:Envelope> String result = null; try { String responseStr = new String(bytes); if (responseStr.indexOf("getTranslationResponse") != -1) { String s = (String) resultEnvelope.getResult(); result = new String(s.getBytes(), CHARSET); outputStringItem.setLabel("Translation:"); outputStringItem.setText(result); } else { midlet.translatorScreenError( "Unexpected response: " + result); } } catch(UnsupportedEncodingException e) { midlet.translatorScreenError(e.toString()); } } } public void handleHttpPosterError(String errorMessage) { stopActivityIndicator(); midlet.translatorScreenError( "Communication error:\n" + errorMessage); } }

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

31

Forum.Nokia.com

5.4

SettingsScreen.java SettingsScreen 为翻译过程中的输入语言和输出语言提供了一个固定的翻译选项集。这些选项必须与 Web 服 务 所 提 供 的 选 项 相 对 应 。 可 以 对 该 MIDlet 进 行 修 改 使 之 能 使 用 该 范 例 Web 服 务 的 getTranslationOptions 请求来更新 Settings(设置)选项列表。 import javax.microedition.lcdui.*; class SettingsScreen extends Form implements CommandListener, ItemStateListener { private static final int DE = 0; private static final int EN = 1; private static final int ES = 2; private static final int FR = 3; private static final int IT = 4; private static final int PT = 5; private static final String[] inputLocaleStrings = { "de", "en", "es", "fr", "it", "pt" }; private static final String[][] outputLocaleArray = { {"en", "fr"} , // row DE: "de" to {"de", "es", "fr", "it", "pt" } , // row EN: "en" to {"en"} , // row ES: "es" to {"de", "en"}, // row FR: "fr" to {"en"} , // row IT: "it" to {"en"} // row PT: "pt" to }; // The default translation setting is from "en" to "fr" static final String DEFAULT_INPUT_LOCALE = "en"; static final String DEFAULT_OUTPUT_LOCALE = outputLocaleArray[EN][2]; // "fr" private final Command cancelCommand; private final Command applyCommand; private final TranslatorMIDlet midlet; private private private private ChoiceGroup inputLocaleChoiceGroup; ChoiceGroup outputLocaleChoiceGroup; int row = EN; int column = 2; // "fr" (see DEFAULT_OUTPUT_LOCALE above)

... ... ... ... ... ...

SettingsScreen(TranslatorMIDlet midlet) { // (this.titleString() can't be referenced // until after super() is called) super(null); setTitle(titleString());

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

32

Forum.Nokia.com

this.midlet = midlet; // Add the input locale setting choices inputLocaleChoiceGroup = new ChoiceGroup("Input locale", ChoiceGroup.EXCLUSIVE, inputLocaleStrings, null); inputLocaleChoiceGroup.setSelectedIndex(row, true); append(inputLocaleChoiceGroup); // Add the output locale setting choices // (based on input locale selected) outputLocaleChoiceGroup = makeOutputLocaleChoiceGroup( outputLocaleArray[row], 0); outputLocaleChoiceGroup.setSelectedIndex(column, true); append(outputLocaleChoiceGroup); setItemStateListener(this); // Add the screen commands cancelCommand = new Command("Cancel", Command.BACK, 1); addCommand(cancelCommand); applyCommand = new Command("Use settings", Command.SCREEN, 1); addCommand(applyCommand); setCommandListener(this); } private String titleString() { return ("Settings: " + inputLocaleStrings[row] + " to " + outputLocaleArray[row][column]); } private ChoiceGroup makeOutputLocaleChoiceGroup(String[] strings, int selectedIndex) { ChoiceGroup cg = new ChoiceGroup("Output locale", ChoiceGroup.EXCLUSIVE, strings, null); cg.setSelectedIndex(selectedIndex, true); return cg; } public void itemStateChanged(Item item) { row = inputLocaleChoiceGroup.getSelectedIndex(); if (item == inputLocaleChoiceGroup) { // replace old output locale choices delete(1);

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

33

Forum.Nokia.com

outputLocaleChoiceGroup = makeOutputLocaleChoiceGroup( outputLocaleArray[row], 0); append(outputLocaleChoiceGroup); column = 0; } else { column = outputLocaleChoiceGroup.getSelectedIndex(); } setTitle(titleString()); } public void commandAction(Command command, Displayable d) { if (command == cancelCommand) { midlet.settingsScreenBack(); } else { // applyCommand: 'Use settings' String inputLocale = inputLocaleStrings[row]; String outputLocale = outputLocaleArray[row][column]; midlet.settingsScreenSave(inputLocale, outputLocale); } } } 5.5 HttpPoster.java 这个类接受对某个特定 URL 的 POST 请求并让其进入队列,以便对其提供先进先出的服务。在其构造 函 数 中 创 建 的 HttpPoster 线 程 大 部 分 时 间 在 run 方 法 中 的 wait 调 用 中 闲 置 。 当 调 用 sendRequest 时,它将该请求和侦听器加入到队列中,并把该线程从 wait 调用中唤醒。该线程从 队列中提取下一个请求,调用 doSend,doSend 发送这个请求,读取响应,并适时调用侦听器的 receiveHttpReponse 方法或 handleHttpError 方法。 这个类一个字节一个字节地写出该请求的每一个字符。SendHttpRequest 的调用者把该请求字符 串转换成 UTF-8 字节阵列。实践中,receiveHttpResponse 方法的实现器应该既能处理 UTF-8 也 能处理 UTF-16 响应。 ( 注 意 : 与 诺 基 亚 论 坛 上 MIDlet 总 结 中 的 范 例 [MIDPNET] 所 提 供 的 HttpPoster 比 较 , 这 里 的 HttpPoster 类还是有所不同的。) import java.io.*; import java.util.*; import javax.microedition.io.*; // This class accepts and queues POST requests for a particular URL, and

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

34

Forum.Nokia.com

// services them in first-in-first-out order. Using the queue allows // it to be thread-safe without forcing its clients ever to block. class HttpPoster implements Runnable { private String url; private volatile boolean aborting = false; private Vector requestQueue = new Vector(); private Vector httpRequestPropertiesQueue = new Vector(); private Vector listenerQueue = new Vector(); HttpPoster(String url) { this.url = url; Thread thread = new Thread(this); thread.start(); } synchronized void sendHttpRequest(byte[] bytes, Hashtable httpRequestProperties, HttpPosterListener listener) throws IOException, UnsupportedEncodingException { httpRequestPropertiesQueue.addElement(httpRequestProperties); requestQueue.addElement(bytes); listenerQueue.addElement(listener); notify(); // wake up sending thread }

public void run() { running : while (!aborting) { Hashtable httpRequestProperties; HttpPosterListener listener; byte[] bytes = null; synchronized (this) { while (requestQueue.size() == 0) { try { wait(); // releases lock } catch (InterruptedException e) {

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

35

Forum.Nokia.com

} if (aborting) { break running; } } httpRequestProperties = (Hashtable) (httpRequestPropertiesQueue.elementAt(0)); bytes = (byte[]) requestQueue.elementAt(0); listener = (HttpPosterListener) (listenerQueue.elementAt(0)); httpRequestPropertiesQueue.removeElementAt(0); requestQueue.removeElementAt(0); listenerQueue.removeElementAt(0); } // sendHttpRequest must have notified us doSend(httpRequestProperties, bytes, listener); } } private void doSend(Hashtable httpRequestProperties, byte[] bytes, HttpPosterListener listener) { HttpConnection conn = null; InputStream in = null; OutputStream out = null; String responseStr = null; String errorStr = null; boolean wasError = false; ByteArrayOutputStream responseBytes = new ByteArrayOutputStream(); try { conn = (HttpConnection) Connector.open(url); // Set the request method conn.setRequestMethod(HttpConnection.POST); // Set the HTTP request header fields Enumeration enumeration = httpRequestProperties.keys(); while(enumeration.hasMoreElements()) { String name = (String) enumeration.nextElement(); String value = (String) httpRequestProperties.get(name); conn.setRequestProperty(name, value); } // Getting the output stream may flush the headers out = conn.openOutputStream(); out.write(bytes);

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

36

Forum.Nokia.com

// // // in

Opening the InputStream will open the connection and read the HTTP headers. They are stored until requested. = conn.openInputStream();

// Get the length and process the data int ch; while ((ch = in.read()) != -1) { responseBytes.write(ch); } // If needed, one could add support for HTTP sessions // using URL re-writing here. See the SumMIDlet example // for more details. } catch (IOException e) { wasError = true; errorStr = "IOException connecting to '" + url + "'"; if (e.getMessage() != null) { errorStr += (": " + e.getMessage()); } } finally { if (in != null) { try { in.close(); } catch (IOException e) { // just ignore, there is nothing we can do } } if (out != null) { try { out.close(); } catch (IOException e) { // just ignore, there is nothing we can do } } if (conn != null) { try { conn.close(); } catch (IOException e)

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

37

Forum.Nokia.com

{ // just ignore, there is nothing we can do } } } if (wasError) { listener.handleHttpPosterError(errorStr); } else { listener.receiveHttpResponse(responseBytes.toByteArray()); } } // The instance is useless after abort has been called. void abort() { aborting = true; synchronized (this) { notify(); // wake up our posting thread and kill it } } boolean isAborting() { return aborting; } } 5.6 HttpPosterListener.java 这 里 是 一 个 接 口 , HttpPoster 用 这 个 接 口 对 其 调 用 者 进 行 回 调 。 在 这 个 范 例 中 , 接 口 是 由 TranslatorScreen 实现的。 interface HttpPosterListener { void receiveHttpResponse(byte[] responseBytes); void handleHttpPosterError(String errorString); } 5.7 ErrorScreen The ErrorScreen is used in MIDlet UI callbacks to handle error situations, where a temporary error dialog needs to be displayed to the end user. ErrorScreen 用于 MIDlet UI 回调,以便处理出错情况,这时需要向最终用户显示一个暂时的出错对话 框。

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

38

Forum.Nokia.com

import javax.microedition.lcdui.*; import java.util.Timer; import java.util.TimerTask; class ErrorScreen extends Alert { private static Image image; private static Display display; private static ErrorScreen instance = null; private ErrorScreen() { super("Error"); setType(AlertType.ERROR); setTimeout(2000); setImage(image); } static void init(Image img, Display disp) { image = img; display = disp; } static void showError(String message, Displayable next) { if (instance == null) { instance = new ErrorScreen(); } instance.setString(message); display.setCurrent(instance, next); } } 5.8 Translator.jad 下面是针对翻译器 MIDlet 的应用描述器。TranslatorService-URL 指向本范例开发并测试的测试机器, 当将本范例安装到某台实际服务器上使用时需要作相应的修改。 MIDlet-1: Translator, /logo.png, TranslatorMIDlet MIDlet-Description: SOAP-based Translator MIDlet MIDlet-Jar-Size: 47809 MIDlet-Jar-URL: Translator.jar MIDlet-Name: Translator MIDlet-Vendor: Forum Nokia MIDlet-Version: 0.2 TranslatorService-URL: http://myhost:8080/translator/1.0/TranslatorService

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

39

Forum.Nokia.com

6 范例翻译器服务 SOAP 消息
注:为方便使用,文档中的请求/响应消息已被“整齐排列”,其中 Content-Length(内容长度)值也 许并不符合“整齐排列”情形。 6.1 getTranslation 请求 POST /translator/1.0/TranslatorService HTTP/1.1 Content-Type: text/xml; charset="UTF-8" Content-Length: 796 Host: myhost:8080 <?xml version="1.0" encoding="UTF-8"?> <SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Body SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <getTranslation xmlns="http://foo.bar/wsd/translator/1.0/wsdl/TranslatorService" id="o0" SOAP-ENC:root="1"> <String_1 xmlns="" xsi:type="xsd:string">en</String_1> <String_2 xmlns="" xsi:type="xsd:string">fr</String_2> <String_3 xmlns="" xsi:type="xsd:string">The quick brown fox jumps over the lazy dog.</String_3> </getTranslation> </SOAP-ENV:Body> </SOAP-ENV:Envelope> 6.2 getTranslation 响应 HTTP/1.1 200 OK Content-Type: text/xml; charset="utf-8" SOAPAction: "" Date: Sat, 01 Feb 2003 11:02:13 GMT Server: Apache Coyote HTTP/1.1 Connector [1.0] <?xml version="1.0" encoding="UTF-8"?> <env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:enc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns0="http://foo.bar/wsd/translator/1.0/types/TranslatorService" env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <env:Body> <ans1:getTranslationResponse xmlns:ans1="http://foo.bar/wsd/translator/1.0/wsdl/TranslatorService"> <result xsi:type="xsd:string">Le renard brun rapide a sauté par-dessus le chien paresseux.</result> </ans1:getTranslationResponse> </env:Body>

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

40

Forum.Nokia.com

</env:Envelope>

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

41

Forum.Nokia.com

7 参考文献
老虎机 网络 MIDlet 范例:老虎机 诺基亚论坛,2002 年 http://www.forum.nokia.com JAXRPC JavaTM APIs for XML based RPC(针对基于 XML 的 RPC 的 JavaTM APIs) Java Community Process, JSR 101 http://www.jcp.org/en/jsr/detail?id=101 J2METM Web 服务规范 Java Community Process, JSR 172 http://www.jcp.org/en/jsr/detail?id=172 Java Web Services Developer Pack (Java Web 服务开发伙伴包), v1.1 http://java.sun.com/webservices/nutshell.html http://www.kxml.org http://www.ksoap.org 网络 MIDlets 简介 诺基亚论坛, 2002 年 http://www.forum.nokia.com MIDPPROG MIDP 编程简介 诺基亚论坛,2002 年 http://www.forum.nokia.com RFC2616 超文本传输协议 – HTTP 1.1 IETF RFC 2616, 1999 年 6 月 http://www.ietf.org/rfc/rfc2616.txt RFC822 ARPA 互联网文本消息格式标准 IETF RFC 822,1982 年 8 月 http://www.ietf.org/rfc/rfc822.txt RFC2109 HTTP 状态管理机制 IETF RFC 2109, 1997 年 2 月 http://www.ietf.org/rfc/rfc2109.txt REST 表达状态传输(Representational State Transfer) http://internet.conveyor.com/RESTwiki/moin.cgi

JSR172

JWSDP

KXML KSOAP MIDPNET

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

42

Forum.Nokia.com

SOAP

Simple Object Access Protocol(SOAP,简单对象访问协议) 1.1 W3C Note 2000 年 5 月 8 日 http://www.w3.org/TR/SOAP

UTF-8

IETF RFC 2279: UTF-8, ISO 10646 转换格式 1998 年 http://www.ietf.org/rfc/rfc2279.txt

UTF-16

IETF RFC 2781: UTF-16, ISO 10646 编码 2000 年 http://www.ietf.org/rfc/rfc2781.txt

WSARCH

Web Services Architecture(Web 服务架构) W3C 工作草案, 2002 年 11 月 14 日 http://www.w3.org/TR/ws-arch/

WSDL

Web Services Definition Language (WSDL,Web 服务定义语言) 1.1 W3C Note, 2001 年 3 月 15 日 http://www.w3.org/TR/WSDL.html

WSIBP

基本协议,版本 1.0 工作小组草案,日期:2002 年 10 月 8 日 http://www.ws-i.org

XML

Extensible Markup Language (XML,可扩展标记语言) 1.0 (Second Edition,第二版) W3C 推荐,2000 年 10 月 6 日 http://www.w3.org/TR/REC-xml

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

43

Forum.Nokia.com

创建 测试 销售
携手诺基亚开发并推广移动应用

1

访问诺基亚论坛 Forum.Nokia.com

Forum.Nokia.com 向内容和应用开发提供所需的各种工具和资源,还向运营商、企业和用户提供销售 渠道。 Forum.Nokia.com

2

下载各种工具和模拟器 Forum.Nokia.com/tools 中 的 链 接 指 向 来 自 诺 基 亚 和 其 他 行 业 领 先 者 ( 包 括 Borland 、 Adobe 、 AppForge、Macromedia、Metrowerks,以及 Sun)的各种工具。 Forum.Nokia.com/tools

3

获取文档和规范
文档专区中准备了各种有用的白皮书、常见问题解答、教程,以及 Symbian OS 和 60 系列平台、J2ME、消息 (包括 MMS)及其它技术的许多 APIs 介绍。Forum.Nokia.com/devices 列出了诺基亚设备的详细技术规范。

Forum.Nokia.com/documents Forum.Nokia.com/devices

4

测试你的应用,获取支持 诺基亚论坛既提供免费支持,也提供收费支持,这些支持使你能直接接触诺基亚工程师和诺基亚设 备,并让全球开发伙伴与你联系在一起。诺基亚 OK 测试计划使你的应用能在诺基亚的各个销售渠道 中享受优惠待遇。 Forum.Nokia.com/support Forum.Nokia.com/ok 通过诺基亚渠道拓展市场 访问 Forum.Nokia.com/business,了解向你开放的所有市场营销渠道,其中包括诺基亚 Tradepoint, 这是一个在线 B2B 市场。

5

Forum.Nokia.com/business 面向全球买家 把你的应用放到诺基亚 Tradepoint,它们将进入全球几十家采购组织的视野。这些买家的范围从主

6

流全球运营商和公司企业到地区性运营商和 XSPs。贵公司和贵公司的应用还会获得地区性诺基亚软 件市场的青睐,并得到更多的全球和地区机会,其中包括对各家运营商的面对面交流、连机和现场 展览、以及受邀参加各种全球性活动等。

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

44

Forum.Nokia.com

Forum.Nokia.com/business

A Brief Introduction to MIDP Clients for Web Services Web 服务 MIDP 客户端简介

45


相关文章:
ch6数显表说明书
CH6 数显仪说明书前 言感谢您选用我公司的产品,我们相信这种数显表会达到您预期的使用目的。 在本说明书内,关于 CH6 数显仪系列方面的内容,将尽可能为您作明确...
RTK技术规范-CHT2009-2010
CH/T2009--2010 全球定位系统实时动态测量(RTK)技术规范 全球定位系统实时动态测量(RTK)技术规范 测量 1 范围 本标准规定了利用全球定位系统实时动态测量(RTK)技术...
ESP8266新手入门调试指导(补全)
CH-PD 换一 个阻值更大的上拉电阻;2.换个承受电流大一点 USB 转 TLL 模块(群众们也可以自己改造) (@ZR(小 R))反应:在供电不足的情况下,收到的响应为...
RKC温控器_CH-102_主要结构及功能_图文
o o o RKC 温控器 - CH-102 o RKC 温控器系列 - 精品推荐 o RKC 温控器 - CB-900 RKC 温控器 - CD-701 RKC 温控器 - CH-102 REX-C400 o o ...
各国国家缩写
CH 41 -7 Syria 叙利亚 SY 963 -6 Countries and Regions 国家或地区 国际域名缩写 电话代码 时差 Taiwan 台湾省 TW 886 0 Tajikstan 塔吉克斯坦 TJ 992 -5...
美国证明
Secretary of State By Assistant Authentication Officer Department of State Issued pursuant to CHXIV, State of Sept. 15, 1789, 1 Stat. 68-69; 22 USC ...
有机作业4(含答案)
A. CH3CH(OH)CH2CH2CH3 B. C6H5COCH3 C. CH3CH2CH2OH D. CH3CHO 31 乙醛和过量甲醛在 NaOH 作用下主要生成: 32 用格氏试剂制备 1-苯基-2-丙醇,...
RKC CH102 说明书
RKC CH102 说明书文章来源:http://www.h7ec.com/ 数字控制器 CH 系统操作手册 1. 产品型号说明 CH□02 □□□-□□*□□-□□①②③④⑤⑥⑦⑧9 D:PI...
USB 转串口232芯片CH340及其应用电路原理图
USB 转串口232芯片CH340及其应用电路原理图_计算机软件及应用_IT/计算机_专业资料。端口外围电路转换 问题的提出。为什么要 USB 转串口?昨天去看了很多电脑主板外围...
HullFund8eCh01ProblemSolutions
HullFund8eCh01ProblemSolutions_经济学_高等教育_教育专区。fundamental of futures and and options market 01 CHAPTER 1 Introduction Practice Questions Problem ...
更多相关标签: