在JAXR客户端使用分类系统
在JAXR API中,一种分类系统是通过一个ClassificationScheme对象来表示的。
本节描述如何使用Java WSDP中的JAXR工具来完成:
· 定义自己的分类系统
· 为机构指定通信地址
定义分类系统
JAXR规范要求一个JAXR提供者能够添加由JAXR客户端使用的用户定义的分类系统。客户用来添加和管理这些分类系统的机制是针对实现的。
Java WSDP中的JAXR的实现使用了简单的基于文件的方法来为JAXR客户端提供分类系统。一旦JAXR提供着启动了,这些文件在运行期间是可读的。
Java WSDP中的分类系统的结构由JAXR预定义概念DTD定义的,在jaxrconcepts.dtd文件以XML方案的形式和jaxrconcepts.xsd文件中都有申明。文件jaxrconcepts.xml包含了用于Java
WSDP中JAXR实现的分类系统。所有的这些文件都包含在<JWSDP_HOME>/common/lib/jaxr-ri.jar文件中,但可以在<JWSDP_HOME>/docs/jaxr/taxonomies目录下发现它的一个副本。该目录还包含Java
WSDP中JAXR的实现在定义著名的分类系统时使用的XML文件的副本,有naics.xml,iso3166.xml,和unspsc.xml。可以将所有这些文件用作如何构建一个分类系统的XML文件的例子。
文件jaxrconcepts.xml中的数据项与下面类似:
<PredefinedConcepts>
<JAXRClassificationScheme id="schId"
name="schName">
<JAXRConcept id="schId/conCode"
name="conName" parent="parentId"
code="conCode">
</JAXRConcept>
...
</JAXRClassificationScheme> </PredefinedConcepts>
分类系统结构是基于包含的结构。元素PredefinedConcepts是结构的根,是必须的。元素JAXRClassificationScheme是结构的双亲,而JAXRConcept元素是孩子和孙子。一个JAXRConcept元素可以有孩子,但不是必须的。
所有元素的定义中,order和case属性是非常重要的。
要增加用户定义的分类系统,按照如下步骤进行:
1. 为分类系统发布JAXRClassificationScheme元素,形成要访问的注册中心中的一个ClassificationScheme对象。例如,可以发布ClassificationScheme对象到Java
WSDP注册中心服务器。为了发布一个ClassificationScheme对象,必须设置它的name。还要给定方案,已知的分类方案中的一类,例如uddi-org:types。在下面的代码段中,name是LifeCycleManager.createClassificationScheme方法调用的第一个参数。
ClassificationScheme cScheme
=
blcm.createClassificationScheme("MyScheme",
"A
Classification Scheme");
ClassificationScheme uddiOrgTypes =
bqm.findClassificationSchemeByName(null,
"uddi-org:types");
if (uddiOrgTypes != null) {
Classification classification
=
blcm.createClassification(uddiOrgTypes,
"postalAddress",
"categorization" );
postalScheme.addClassification(classification);
ExternalLink externalLink
=
blcm.createExternalLink(
"http://www.mycom.com/myscheme.html",
"My
Scheme");
postalScheme.addExternalLink(externalLink);
Collection schemes = new ArrayList();
schemes.add(cScheme);
BulkResponse br =
blcm.saveClassificationSchemes(schemes);
}
由saveClassificationSchemes方法返回的BulkResponse对象包含分类方案的关键字,它是用户要查找的:
if (br.getStatus() == JAXRResponse.STATUS_SUCCESS)
{
System.out.println("Saved
ClassificationScheme");
Collection schemeKeys = br.getCollection();
Iterator keysIter = schemeKeys.iterator();
while (keysIter.hasNext())
{
javax.xml.registry.infomodel.Key
key =
(javax.xml.registry.infomodel.Key)
keysIter.next();
System.out.println("The
postalScheme key is " +
key.getId());
System.out.println("Use
this key as the scheme" +
"
uuid in the taxonomy file");
}
}
2. 在一个XML文件中,定义一个分类系统的结构,它是遵循JAXR预定义概念DTD的。在分类系统的XML文件输入ClassificationScheme元素,指定返回的关键字ID值作为id属性的值,名字作为name属性的值。例如,对于上面的代码段,空的JAXRClassificationScheme元素标记类似于下面的例子(所有的都在一行):
<JAXRClassificationScheme
id="uuid:nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn"
name="MyScheme">
ClassificationScheme的id 必须是UUID。
3. 在分类系统的XML文件中输入每个JAXRConcept元素,指定下面的四个属性,按照这一次序:
a.
id是JAXRClassificationScheme的id值,后面跟/分隔符,再跟上JAXRConcept元素的代码
b.
name是JAXRConcept元素的名字
c.
parent是直接的双亲id(或者是ClassificationScheme的id,或者是双亲JAXRConcept的id)
d.
code是JAXRConcept元素代码的值
naics.xml文件中的第一个JAXRConcept元素如下所示(所有的都在一行):
<JAXRConcept
id="uuid:C0B9FE13-179F-413D-8A5B-5004DB8E5BB2/11"
name="Agriculture, Forestry, Fishing and Hunting"
parent="uuid:C0B9FE13-179F-413D-8A5B-5004DB8E5BB2"
code="11"></JAXRConcept>
4. 要添加用户定义的分类系统的结构到JAXR提供者,运行客户端程序时,指定系统属性com.sun.xml.registry.userTaxonomyFilenames。命令行(都在一行)如下所示。垂直竖线(|)是文件分隔符。
java myProgram -DuserTaxonomyFilenames=
c:\myfile\xxx.xml|c:\myfile\xxx2.xml
在build.xml文件中,可以使用<sysproperty>标记来设置该属性。或者在程序中,如下设置该属性:
System.setProperty
("com.sun.xml.registry.userTaxonomyFilenames",
"c:\myfile\xxx.xml|c:\myfile\xxx2.xml");
指定通信地址
JAXR规范将通信地址定义成由属性street,city,country等构成的结构化接口。另一方面,UDDI规范将通信地址定义成自由格式的地址行的集合,每一行可以被赋予一个含义。要将JAXR的PostalAddress格式映射成一个已知的UDDI地址格式,必须将UDDI格式指定成一个ClassificationScheme对象,然后指定UDDI格式分类方案中的概念与JAXR
PostalAddress分类方案中的注释间的语义等价。JAXR PostalAddress分类方案由Java
WSDP中的JAXR的实现提供。
在JAXR API中,一个PostalAddress对象有成员streetNumber, street,
city, state, postalCode和country。在Java WSDP中的JAXR的实现中,jaxrconcepts.xml文件里有预定义的概念,在ClassificationScheme内名为PostalAddressAttributes。
要指定JAXR通信地址格式和其他格式间的映射,需要设置两个连接属性:
· javax.xml.registry.postalAddressScheme属性,它为连接指定了一个通信地址分类方案
· javax.xml.registry.semanticEquivalences属性,它指定了JAXR格式和其他格式间的语义等价
例如,假设要使用已经发布到IBM注册中心的方案,已知UUID为uuid:6eaf4b50-4196-11d6-9e2b-000629dc0a2b。该方案已经在jaxrconcepts.xml文件中存在,在名字IBMDefaultPostalAddressAttributes下。
<JAXRClassificationScheme
id="uuid:6EAF4B50-4196-11D6-9E2B-000629DC0A2B"
name="IBMDefaultPostalAddressAttributes">
首先,使用JAXRClassificationScheme元素(UUID)中的id值来指定通信地址方案。情况并不重要:
props.setProperty("javax.xml.registry.postalAddressScheme",
"uuid:6eaf4b50-4196-11d6-9e2b-000629dc0a2b");
接着,指定从默认的JAXR通信地址方案中的每个JAXRConcept元素到IBM方案中的counterpart的id的映射:
props.setProperty("javax.xml.registry.semanticEquivalences",
"urn:uuid:PostalAddressAttributes/StreetNumber,"
+
"urn:uuid:6eaf4b50-4196-11d6-9e2b-
000629dc0a2b/StreetAddressNumber|" +
"urn:uuid:PostalAddressAttributes/Street,"
+
"urn:uuid:6eaf4b50-4196-11d6-9e2b-
000629dc0a2b/StreetAddress|" +
"urn:uuid:PostalAddressAttributes/City,"
+
"urn:uuid:6eaf4b50-4196-11d6-9e2b-000629dc0a2b/City|"
+
"urn:uuid:PostalAddressAttributes/State,"
+
"urn:uuid:6eaf4b50-4196-11d6-9e2b-000629dc0a2b/State|"
+
"urn:uuid:PostalAddressAttributes/PostalCode,"
+
"urn:uuid:6eaf4b50-4196-11d6-9e2b-000629dc0a2b/ZipCode|"
+
"urn:uuid:PostalAddressAttributes/Country,"
+
"urn:uuid:6eaf4b50-4196-11d6-9e2b-000629dc0a2b/Country");
使用这些属性生成连接后,可以生成一个通信地址并在发布机构前,将它赋值给机构的主要联系:
String streetNumber = "99";
String street = "Imaginary Ave. Suite 33";
String city = "Imaginary City";
String state = "NY"; String country = "USA";
String postalCode = "00000";
String type = "";
PostalAddress postAddr =
blcm.createPostalAddress(streetNumber,
street, city, state,
country, postalCode, type);
Collection postalAddresses = new ArrayList();
postalAddresses.add(postAddr);
primaryContact.setPostalAddresses(postalAddresses);
然后,如果通信地址方案和查询用的等价语义与发布指定的相同,JAXR查询可以使用PostalAddress方法来查找通信地址。当不知道发布时使用的通信地址方案时,要查找通信地址,可以用Slot对象的集合的方式进行查找。JAXRQueryPostal.java例子应用程序演示了如何实现这一个过程。
一般来说,可以为任意的使用uddi-org:types分类系统中著名分类的postalAddress
tModel生成一个用户定义的通信地址分类系统,它的tModel UUID为uuid:c1acf26d-9672-4404-9d70-39b756e62ab4,有一个postalAddress的值。可以查找tModel
overviewDoc,它指向方案规范中的技术细节,在那儿可以找到分类系统的结构定义。(overviewDoc与JAXR中的ExternalLink等价。)
运行客户端例子
该指南提供了简单的可以从命令行运行的客户端应用程序。可以修改它来适应你的需求。这些应用程序还允许指定IBM注册中心、Microsoft注册中心或者用于查询和更新的注册中心服务器;可以指定任意其它的UDDI版本2注册中心。
目录<JWSDP_HOME>/docs/tutorial/examples/jaxr中有如下一些客户端实例:
· JAXRQuery.java
演示了如何查找注册中心中的某个机构
· JAXRQueryByNAICSClassification.java
演示了如何使用通用的分类方案来查找注册中心
· JAXRQueryByWSDLClassification.java
演示了如何查找注册中心中借助于WSDL文档描述自身的那些Web服务
· JAXRPublish.java显示了如何将某个机构发布到注册中心
· JAXRDelete.java显示了如何从注册中心移除一个机构
· JAXRSaveClassificationScheme.java
显示了如何发布一个分类方案(特殊的,通信地址方案)到注册中心
· JAXRPublishPostal.java显示了如何用主要联系用的通信地址来发布一个机构
· JAXRQueryPostal.java显示了如何从一个机构中检索通信地址数据
· JAXRDeleteScheme.java
显示了如何从一个注册中心删除一种分类方案
· JAXRGetMyObjects.java列出注册中心中所拥有的全部对象
目录 <JWSDP_HOME>/docs/tutorial/examples/jaxr还包括:
· 实例的build.xml文件
· 供例子程序使用的字符串值的JAXRExamples.properties文件
· 名为postalconcepts.xml的文件,它在通信地址的例子中使用
编译例子程序前
编译例子程序前,如下编辑JAXRExamples.properties文件。(关于编辑该文件来访文注册中心服务器的详细信息,请参见“使用JAXR来访问注册中心服务器”。)
1. 在JAXRExamples.properties文件中编辑下列这几行来指定想要访问的注册中心。对于queryURL和publishURL的赋值,除了希望访问的注册中心,全部注释掉。默认的是注册中心服务器,因此如果要使用注册中心服务器,不必修改这部分。
## Uncomment one pair of query
and publish URLs.
## IBM:
#query.url=http://uddi.ibm.com/testregistry/inquiryapi
#publish.url=https://uddi.ibm.com/testregistry/protect/
publishapi
## Microsoft:
#query.url=http://uddi.microsoft.com/inquire
#publish.url=https://uddi.microsoft.com/publish
## Registry Server:
query.url=http://localhost:8080/registry-server/
RegistryServerServlet
publish.url=http://localhost:8080/registry-server/
RegistryServerServlet
IBM和Microsoft注册中心都拥有相当多的数据,可以在其中执行查询。而且,如果仅仅执行查询,不必注册。
没有包含SAP注册中心的URL,可以自由的添加。
如果想要发布任意的公共注册中心,用于访问注册中心的注册处理并不难(参见:“预备:访问注册中心”)。但是,每个注册中心在同一时刻只允许注册一个机构。如果将某个机构注册到其中的某个注册中心,在发布另一个前必须删除它。由于JAXRPublish例子发布的机构是虚构的,不管怎样可以直接删除。(有提示地删除这样的机构是非常重要的,因为发布的注册中心彼此间会复制数据,虚构的机构可以出现在没有在其中发布的注册中心,因此不能从中删除。)
注册服务器使得你可以更自由的使用JAXR进行试验。可以注册所希望的多个机构。但是,该注册中心开始时数据库为空,因此执行查询前必须自己发布机构到注册中心。
2. 编辑JAXRExamples.properties文件中的下面几行来指定注册到注册中心时获得的用户名和密码。默认值是注册中心服务器默认的密码。
## Specify username and password
if needed
## testuser/testuser are defaults for Registry Server
registry.username=testuser
registry.password=testuser
3. 如果将要使用公共的注册中心,编辑JAXRExamples.properties文件中的下面几行,包含空字符串的代理主机,指定自己的代理设置。代理主机是网络上,系统访问Internet时要通过的;通常在Internet浏览器中指定它的设置。可以保持空值来使用注册中心服务器。
## HTTP and HTTPS proxy host
and port;
## ignored by Registry Server
http.proxyHost=
http.proxyPort=8080
https.proxyHost=
https.proxyPort=8080
代理端口值为8080,这是常用的一个;如果使用了不同的端口,修改这个字符串。
对于公共注册中心,数据项通常有如下模式:
http.proxyHost=proxyhost.mydomain
http.proxyPort=8080
https.proxyHost=proxyhost.mydomain
https.proxyPort=8080
4. 在文件的剩余部分自由的修改任意机构的数据。在发布和通信地址例子中将使用这些数据。
任何时候都可以编辑JAXRExamples.properties文件。运行客户例子时,会使用最新版的该文件。
编译例子
要编辑程序,进入<JWSDP_HOME>/docs/tutorial/examples/jaxr目录。build.xml文件允许使用下面的命令
ant build
来编译所有的例子。Ant工具生成名为build的子目录,并将class文件放置在该目录中。
注意到在build.xml文件中,classpath的设置包括几个目录的内容。所有的JAXR客户端例子都需要设置classpath。
运行例子
用于运行例子的一些build.xml目标包含注释掉的<sysproperty>标记,它是设置JAXR记录层来调试和设置其它连接属性的。提供这些标记来演示如何指定连接属性。这些标记可以自由的修改或删除。
如果正使用注册中心服务器运行例子,启动Tomcat。更多信息请参见“启动注册中心服务器”。要运行公共注册中心上的例子,不必启动Tomcat。
运行JAXRPublish例子
要运行JAXRPublish程序,使用不带命令行参数的run-publish目标:
ant run-publish
程序output显示新机构关键字的字符串值,机构名为“The Coffee Break.”
运行JAXRPublish程序后,JAXRDelete程序前,可以运行JAXRQuery来查找你发布的机构。也可以使用注册中心浏览器来查找。
运行JAXRQuery例子
要运行JAXRQuery例子,使用Ant目标run-query。在命令行指定一个查询字符串作为参数,来查找注册中心中名字包含该字符串的机构。例如,下面的命令行查找名字包含“coff”的机构(查找是不区分大小写的):
ant run-query -Dquery-string=coff
运行JAXRQueryByNAICSClassification例子
运行完JAXRPublish程序后,也可以运行JAXRQueryByNAICSClassification例子,它查找使用“Snack
and Nonalcoholic Beverage Bars”分类的机构,同样用于由JAXRPublish生成的机构。要完成这一任务,使用Ant目标run-query-naics:
ant run-query-naics
运行JAXRDelete例子
要运行JAXRDelete程序,指定由JAXRPublish程序返回的关键字串作为输入给run-delete目标:
ant run-delete -Dkey-string=keyString
运行JAXRQueryByWSDLClassification例子
任何时候都可以运行JAXRQueryByWSDLClassification例子。使用Ant目标run-query-wsdl:
ant run-query-wsdl
这个例子从公共注册中心返回许多结果,可能要运行几分钟。
发布一种分类方案
为了发布带有通信地址的机构到公共注册中心,必须首先为通信地址发布一种分类方案。
要运行JAXRSaveClassificationScheme程序,使用目标run-save-scheme:
ant run-save-scheme
程序返回一个UUID字符串,在下一节将会使用该串。
如果正在使用注册中心服务器,可以不必运行该程序,因为没有使这些对象生效。
公共注册中心允许同时拥有多个分类方案(通常分类方案和概念加在一起的总数不超过10)。
运行通信地址的例子
运行通信地址的例子前,在编辑器中打开postalconcepts.xml文件。找到字符串uuid-from-save,用run-save-scheme目标返回的UUID字符串替换它。对于注册中心服务器,可以使用格式为UUID的任意字符串。
对于一个给定的注册中心,只要保存分类方案和编辑的postalconcepts.xml一次。执行完这两步后,可以多次运行JAXRPublishPostal和JAXRQueryPostal程序。
1. 运行JAXRPublishPostal程序。注意,在build.xml文件中,run-publish-postal目标包含一个<sysproperty>标记,它将userTaxonomyFilename属性设置成当前目录中postalconcepts.xml文件的位置:
<sysproperty
key="com.sun.xml.registry.userTaxonomyFilenames"
value="postalconcepts.xml"/>
指定在postalconcepts.xml文件中输入的字符串作为run-publish-postal目标的输入:
ant run-publish-postal -Duuid-string=uuidstring
程序output显示新机构的关键字的值串。
2. 运行JAXRQueryPostal程序。Run-query-postal目标包含与run-publish-postal目标相同的<sysproperty>标记。
在命令行指定一个query-string参数和一个uuid-string参数作为run-query-postal目标的输入,来在注册中心中查找由run-publish-postal目标发布的机构:
ant run-query-postal -Dquery-string=coffee
-Duuid-string=uuidstring
使用JAXR的PostalAddress方法将得到正确的主要联系用的通信地址。使用其它通信地址方案找到的任何通信地址将以缝隙行的形式出现。
3. 如果正使用公共注册中心,确保按照“运行JAXRDelete例子”中的指令删除了已经发布的机构。
删除分类方案
使用完后要删除发布的分类方案,使用run-delete-scheme目标来运行JAXRDeleteScheme程序:
ant run-delete-scheme -Duuid-string=uuidstring
对于UDDI注册中心来说,删除一个分类方案是逻辑上将它从注册中心移除,并没有物理上删除。不能再使用这一分类方案,但例如,如果调用QueryManager.getRegisteredObjects方法,该方案仍然是可见的。由于公共注册中心允许拥有10个这样的对象,这不是个问题。
获得注册的对象的列表
要获得在注册中心已经拥有的对象、机构和分类方案的列表,通过使用run-get-objects目标来运行JAXRGetMyObjects程序:
ant run-get-objects
其它目标
要删除build目录和class文件,使用命令:
ant clean
要获得目标的语法提示,使用命令:
ant -projecthelp
更多信息
关于JAXR、注册中心以及Web服务的更多信息,可以参考下列:
· Java规范请求 (JSR)
93: JAXR 1.0:
http://jcp.org/jsr/detail/093.jsp
· JAXR主页:
http://java.sun.com/xml/jaxr/index.html
· 统一描述、发现和集成(Universal
Description, Discovery, and Integration,UDDI)项目:
http://www.uddi.org/
· ebXML:
http://www.ebxml.org/
· 用于ebXML注册中心的开放源代码JAXR提供着
https://sourceforge.net/forum/forum.php?forum_id=197238
· Java Web服务开发包(Java
WSDP):
http://java.sun.com/webservices/webservicespack.html
· Java技术和XML:
http://java.sun.com/xml/
· Java技术和Web服务:
http://java.sun.com/webservices/index.html
|