SCA 组合应用程序中的组件可以在网络中的不同节点上运行。在 Apache Tuscany 中,可以使用 SCA 域管理一组节点。在 SCA 中,组合、组件、其实现和运行它们的节点属于一个所谓的 SCA 域 。 诸如 Tuscany 等 SCA 实现提供了管理工具,允许系统管理员管理域中的 SCA 构件。使用域可为您提供在将节点添加到域时指定节点安装特征(例如主机和端口)的灵活性,而不是在组合文件中指定这些特征。本文演示如何通过 SCA 域管理由许多 SCA 组件组成的应用程序。了解将 SCA 应用程序添加到域所涉及到的每个步骤。
本文中使用的示例是“Getting started with Tuscany”指南(请参见参考资料 部 分提供的相关链接)中的商店应用程序。虽然“Getting started with Tuscany”指南使用了 Eclipse 来部署应用程序,但是本文将向您介绍如何在实际生产环境中运行同一个应用程序。本文使用一个无需附加的中间件要求即可在独立 Tuscany 运行时中运行的应用程序来演示所需的步骤。
确保您已经:
在开始部署解决方案之前,您需要获得解决方案的安装存档。这些存档包含 SCA 贡献包 (contribution)、组合应用和 SCA 组件,下面的部分将简要描述这些概念。该商店解决方案包含三个 Eclipse 项目:
store
UI 的必需 Java™ 实现(请参见图 1)。 将这些项目作为 JAR 文件导出到 c:\repository 目录中。如果下载完整的 Tuscany 1.3.1 分发包,您将在 Tuscany 分发包目录的 tutorial 子目录中发现已经导出的该商店示例的 JAR 文件。这些文件包括:
在继续之前,让我们简要描述一下以下 SCA 和 Tuscany 概念:
域中的所有 SCA 资源——贡献包、组合和节点——全都是可通过 HTTP 进行访问的 Web 资源。这些资源的集合可通过 Atom 进行访问,并且可以使用 Atompub 进行管理。这是 SCA 和 Tuscany 标准。(有关 Atom 发布协议的描述,请参阅参考资料 。)
将 SCA 组件安装到 Tuscany 域涉及到以下步骤:
让我们在下面几个部分中分别介绍这些步骤。
java -jar \tuscany-sca-1.3.1\modules\tuscany-node2-launcher-1.3.1.jar domain
现在您需要添加包含应用程序构件的贡献包。要成功添加和使用某个贡献包,域管理器和运行应用程序的节点都必须能够访问该贡献包,因为它们需要在运行时加载这些构件。如果所有组件都位于相同主机上,则可以指定文件路径。在分布式部署中,您可以使用以下配置之一:
第一个选项是首选选项,因为它允许多人参与分布式 SCA 域。
为简单起见,在此示例中,让我们假设所有节点在同一主机上运行。在适当的时候,我们将指出本地和分布式部署之间的差异。
http://myassets
(请参见图 7)。 http://myws
和 http://mystore
)分别对 tutorial-web-services.jar 和 tutorial-store.jar 重复上述步骤。如果正确添加了贡献包,您现在应该看到如图 8 所示的列表。 在此示例中,您使用 GUI 将贡献包添加到了 SCA 域。还可以使用程序添加贡献包。在 Tuscany 1.3.1 中,这可以通过将包含贡献包的贡献包名称和 URI 的表单发送到域管理器 URL(<domainURL>/workspace)来完成。例如,要为 tutorial-web-services.jar 贡献包发送的条目类似于清单 1。
<?xml version='1.0' encoding='UTF-8'?> <entry xmlns='http://www.w3.org/2005/Atom'> <title>Contribution - http://myws</title> <id>http://myws</id> <link href="file:/c:/repository/tutorial-web-services.jar"/> </entry> |
可以使用清单 2 中的代码将贡献包添加到 SCA 域。
String contributionURI = "http://myws"; String contributionLocation = "file:/c:/repository/tutorial-web-services.jar"; String domainURL = "http://localhost:9990"; try { String entry = "<?xml version=\'1.0\' encoding=\'UTF-8\'?>"+ "<entry xmlns=\'http://www.w3.org/2005/Atom\'>" + "<title>Contribution - " + contributionURI +"</title>" + "<id>" + contributionURI+ "</id>" + "<link href=\"" + contributionLocation + "\" />" + "</entry>"; post(domainURL+"/workspace", entry); } catch (MalformedURLException e1) { // from post() method e1.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } |
在清单 2 中,contributionLocation
是贡献包存储库中或磁盘上的贡献包存档的 URL。在本文使用的示例中,tutorial-web-services.jar 的贡献包位置将是 file:/c:/repository/tutorial-web-services.jar。
清单 2 使用了 post()
方法。这个本地方法使用 Java java.net.URLConnection
类将字符串发送到某个 URL。(有关用于将字符串发送到 URL 的代码,请参阅参考资料 。)将此表单发送到 URL 时,将 URLConnection
对象的 Content-Type 请求属性设置为 "application/atom+xml"
,如清单 3 所示。
清单 3. 设置 URLConnection 对象的 Content-Type 请求属性
URL url = new URL (targetURL); URLConnection conn = url.openConnection(); conn.setDoInput (true); conn.setDoOutput (true); // Disable use of caches. conn.setUseCaches (false); conn.setRequestProperty("Content-Type","application/atom+xml"); [...] |
下一步是将组合添加到域。此示例中共有三个组合:
首先添加 catalogs.composite
。观察该组合的内部可以看到,其目标命名空间为 http://services。它位于您刚才使用命名空间 http://myws 添加的 tutorial-web-services.jar 贡献包中。
还可以通过脚本或程序添加组合。在此示例中,您可以通过将清单 4 中的 XML 发送到 URL http://localhost:9990/composite,从而将 catalogs.composite 添加到域。
<?xml version='1.0' encoding='UTF-8'?> <entry xmlns="http://www.w3.org/2005/Atom"> <title>composite:http://myws;http://services;catalogs</title> <id>composite:http://myws;http://services;catalogs</id> </entry> |
标题和 ID 需要包含如下语法的字符串: composite:contribution-namespace;composite-namespace;composite-name
.
清单 5 显示了从 Java 程序中完成此任务所需要的代码。
String compositeName = "catalogs"; String compositeNamespace = "http://services"; String contributionURI = "http://myws"; String domainURL="http://localhost:9990"; String id = "composite:"+contributionURI+";"+compositeNamespace+";"+compositeName; String entry= "<?xml version=\'1.0\' encoding=\'UTF-8\'?>" + "<entry xmlns=\"http://www.w3.org/2005/Atom\">" + "<title>" + id +"</title>" + "<id>" + id + "</id>" + "</entry>"; try { post(domainURL+"/composite", entry); } catch (Exception e) { e.printStackTrace(); } |
最后一个步骤是为每个组合创建节点。请记住,节点提供在其中运行组合的 Tuscany 运行时环境。在此步骤中,您需要为节点指定主机和端口。也可以在组合本身中指定此信息。但是,务必要注意的是,在分布式环境中,在组合中省略此信息并在节 点创建过程中指定此信息,可以实现更高的应用程序组件部署灵活性。这样做意味着,您不会将组合与其部署位置绑定,并且在某个时候需要将组合移动到不同的主 机或端口时,您将不需要更改此信息。通常,应用程序开发人员不知道将在其中安装应用程序的环境中有哪些端口可用。然而在此步骤中,需要提供可用的端口。
如果打算在本地主机上运行节点,请在 URL 中指定 localhost
并选择可用的端口。由于您的目录节点在独立 Tuscany 环境中运行,您可以指定任何可用的 TCP/IP 端口。如果将 catalogs 组合中的组件实现为 Web 应用程序,则节点将在 Web 容器中运行,并且您必须指定 Web 容器中配置的相应 URL。
如果打算在远程主机上运行节点,您需要确保远程主机已安装了 Tuscany 运行时,并且用于运行节点所必需的贡献包可通过您在添加贡献包时指定的 URL 进行访问。
在此例中,让我们使用本地主机(请参见图 11)。
您还可以通过将清单 6 中的条目发送到位于 cloud 上下文根的域,从而在 Java 程序中将节点添加到域。在此示例中,您可以通过将清单 6 所示的条目发送到 http://localhost:9990/cloud,从而添加 catalogs.composite 的节点。
如果在上面的步骤中手动添加节点,您可以单击节点的名称。您将看到清单 6 所示的条目的内容确切对应于您单击该节点时所看到的内容。这是描述该节点的组合文件。其中包括节点名称(在此例中为 MyCatalogsNode
)、您在为其创建节点的组合(在此例中为 catalogs
)、为其创建节点的组合的命名空间(这里为 http://services
),以及在支持该节点与其他节点之间通信的绑定中指定的节点的主机和端口信息。
<?xml version='1.0' encoding='UTF-8'?> <entry xmlns="http://www.w3.org/2005/Atom"> <id> composite:http://tuscany.apache.org/cloud;http://tuscany.apache.org/cloud;MyCatalogsNode </id> <content type="text/xml"> <composite xmlns="http://www.osoa.org/xmlns/sca/1.0" xmlns:t="http://tuscany.apache.org/xmlns/sca/1.0" targetNamespace="http://tuscany.apache.org/cloud" xmlns:c="http://services" name="MyCatalogsNode"> <component name="MyCatalogsNode""> <t:implementation.node uri="http://myws" composite="c:catalogs"/> <service name="Node"> <binding.ws uri="http://localhost:8081"> <t:binding.http uri="http://localhost:8081"/> <t:binding.jsonrpc uri="http://localhost:8081"/> <t:binding.atom uri="http://localhost:8081"/> </service> </component> </composite> </content> </entry> |
请注意,此示例将 http://localhost
用于节点的 URI。如果将在与域管理器的主机不同的计算机上启动节点,则需要指定将运行节点的计算机的名称,而不是指定 localhost
。
清单 7 中的示例 Java 代码将清单 6 中的条目发送到域。
String compositeName = "catalogs"; String contributionURI = "http://myws"; String compositeNamespace = "http://services"; String nodeName = "MyCatalogsNode"; String domainURL="http://localhost:9990"; String host = "localhost"; String port = "8081"; String nodeIdEntry = "composite:" + "http://tuscany.apache.org/cloud" + ";" + "http://tuscany.apache.org/cloud" + ';' + nodeName; String addNodeEntry = "<?xml version=\'1.0\' encoding=\'UTF-8\'?>" + "<entry xmlns=\"http://www.w3.org/2005/Atom\">" + "<id>" + nodeIdEntry + "</id>" + "<content type=\"text/xml\">" + "<composite xmlns=\"http://www.osoa.org/xmlns/sca/1.0\"\n" + "xmlns:t=\"http://tuscany.apache.org/xmlns/sca/1.0\"\n" + "targetNamespace=\"http://tuscany.apache.org/cloud\"\n" + "xmlns:c=\""+ compositeNamespace + "\"\n" + "name=\""+nodeName + "\">\n\n" + "<component name=\"" +nodeName +"\">\n" + "<t:implementation.node uri=\""+contributionURI + "\" composite=\"c:" + compositeName +"\"/>\n" + "<service name=\"Node\">" + "<binding.ws uri=\"http://"+host+":"+port+"\"/>\n" + "<t:binding.http uri=\"http://"+host+":"+port+ "\"/>\n" + "<t:binding.jsonrpc uri=\"http://"+host+":"+port+"\"/>\n" + "<t:binding.atom uri=\"http://"+host+":" + port +"\"/>\n </service>\n" + "</component>\n</composite>\n</content>\n</entry>"; try { post(domainURL+"/cloud", addNodeEntry); } catch (Exception e) { e.printStackTrace(); } |
现在可以启动节点了。可以采用多种方法启动 Tuscany 中的 SCA 运行时节点:
java -jar <tuscany-install>/modules/tuscany-node2-launcher-1.3.1.jar <domainURL>/node-config/<nodeName>
<tuscany-install>
是您安装 Tuscany 分发包的目录。例如,c:\tuscany-sca-1.3.1
;<domainURL>
是域管理器的 URL,例如 http://localhost:9990
;<nodeName>
是您在创建节点时输入的节点名称,例如 MyCatalogsNode。由于您是在运行节点的主机上发出命令,您可以在这里使用 localhost
,如清单 8 所示。 import org.apache.tuscany.sca.node.launcher.LauncherException; import org.apache.tuscany.sca.node.launcher.NodeLauncher; import org.apache.tuscany.sca.node.SCANode2; ... NodeLauncher nodeLauncher = NodeLauncher.newInstance(); String domainURL = "http://localhost:9990"; // could be read from input argument String nodeName = "MyCatalogsNode"; SCANode2 node; try { node = nodeLauncher.createNode(domainURL+"/node-config/"+nodeName); node.start(); } catch (LauncherException e) { System.out.println("Exception starting node"); e.printStackTrace(); } ... |
请注意,清单 8 中的代码要求将 <tuscany-install>/lib 目录中的 Tuscany 库添加到项目的类路径。
图 13 显示了启动节点的命令的示例输出。在此输出中,所显示的节点 URL 表明了运行节点的实际主机名称,而 Tuscany 运行时则安装在 c:\tuscany\tuscany-sca-1.3.1 目录中。
现在可以在 Web 浏览器中测试应用程序了。该应用程序在您为 store.composite 添加节点时所选择的端口上运行。您将其命名为 MyStoreNode。例如,如果是在本地主机上运行应用程序,您可以将浏览器指向位于 http://localhost:8083/ui/store.html 的应用程序(请参见图 14)。
您现在可以使用该应用程序从目录中选择商品,将商品添加到购物车,清空购物车,以及付款后离开。
您了解了如何使用 Tuscany 域管理器应用程序在 SCA 域中部署 SCA 应用程序。在此示例中,您在没有 Web 容器或应用程序服务器的 J2SE 中运行 Tuscany 运行时。对于更复杂的配置,SCA 域还可以包括运行 IBM WebSphere Application Server、IBM WebSphere Process Server、Apache Geronimo、Apache Tomcat 或其他应用程序服务器的节点。后续的相关文章将进一步深入介绍有关如何将组合应用程序部署到这些不同环境的细节。
学习
获得产品和技术
讨论
参与 developerWorks Blog ,从而加入到 developerWorks 社区中来。
来自 http://www.ibm.com/developerworks/cn/webservices/ws-sca-tuscany/index.html