| // |
| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| // |
| |
| = 在 NetBeans IDE 中使用 CDI 将 OSGi 包作为服务注入 |
| :jbake-type: tutorial |
| :jbake-tags: tutorials |
| :jbake-status: published |
| :icons: font |
| :syntax: true |
| :source-highlighter: pygments |
| :toc: left |
| :toc-title: |
| :description: 在 NetBeans IDE 中使用 CDI 将 OSGi 包作为服务注入 - Apache NetBeans |
| :keywords: Apache NetBeans, Tutorials, 在 NetBeans IDE 中使用 CDI 将 OSGi 包作为服务注入 |
| |
| 本文档介绍了 NetBeans IDE 中对link:http://www.osgi.org/Main/HomePage[+开放服务网关协议+] (OSGi) 的集成支持如何简化创建 OSGi 包并在项目中使用该包的流程。在本教程中,将首先通过 Maven OSGi 包原型创建两个简单的 OSGi 包,然后将这些包部署到 GlassFish Server Open Source Edition 3.1 中。 |
| |
| 创建基本的 OSGi 包后,将创建 Web 客户端应用程序,并使用 CDI 将这些包作为服务注入。然后,将 Web 应用程序作为包部署到服务器。本教程接着将介绍如何使用 OSGi 管理控制台处理 OSGi 包。 |
| |
| 在企业应用程序中使用 OSGi 包可以为更新各个包提供更大的模块性和灵活性。GlassFish Server 中对 OSGi 的便捷支持可以轻松将包合并到应用程序中。 |
| |
| 本教程基于 link:http://blogs.oracle.com/arungupta/entry/totd_154_dynamic_osgi_services[+TOTD #154:GlassFish 3.1 中的动态 OSGi 服务 - 使用 CDI 和 @OSGiService+] 博客帖子和其他博客条目(可在 link:http://blog.arungupta.me/[+Arun Gupta 的博客+]上找到)。请确保访问此博客,并查看许多其他有关使用 OSGi 的优秀博客。 |
| |
| 此外,以下资源中包含各种有关在混合应用程序中使用 OSGi 和 CDI 的信息。 |
| |
| * link:http://weblogs.java.net/blog/2009/06/14/developing-hybrid-osgi-java-ee-applications-glassfish[+在 GlassFish 中开发混合应用程序 (OSGi + Java EE)+] |
| * link:http://blogs.oracle.com/sivakumart/entry/typesafe_injection_of_dynamic_osgi[+在混合 Java EE 应用程序中以类型安全的方式注入动态 OSGi 服务+] |
| * link:http://weblogs.java.net/blog/2009/06/04/osgi-enabled-web-applications-inglassfish[+GlassFish 中启用 OSGi 的 Web 应用程序+] |
| * link:http://www.youtube.com/watch?v=vaOpJJ-Xm70[+ YouTube 视频:通过 GlassFish 3.1 和 CDI 以类型安全的方式注入 OSGi 动态服务 +] |
| * link:http://glassfish.java.net/public/GF-OSGi-Features.pdf[+ 使用 GlassFish Server 进行 OSGi 应用程序开发+] [PDF] |
| |
| *教程练习* |
| |
| image::images/netbeans-stamp-80-74-73.png[title="此页上的内容适用于 NetBeans IDE 7.2、7.3、7.4 和 8.0"] |
| |
| * <<Exercise_1,创建父 POM 项目>> |
| * <<Exercise_2,创建 OSGi 包项目>> |
| * <<Exercise_2a,创建 MavenHelloServiceApi 接口包>> |
| * <<Exercise_2b,创建 MavenHelloServiceImpl 实现包>> |
| * <<Exercise_2c,构建和部署 OSGi 包>> |
| * <<Exercise_3,创建 Web 客户端应用程序>> |
| * <<Exercise_3a,在 POM 项目中配置依赖关系>> |
| * <<Exercise_3b,创建 MavenHelloWebClient Web 应用程序>> |
| * <<Exercise_3c,以包的形式构建 Web 应用程序>> |
| * <<Exercise_3d,部署 Web 应用程序包>> |
| * <<Exercise_4,安装和使用 OSGi 管理控制台>> |
| * <<Exercise_5,参考和深入阅读>> |
| |
| *要学习本教程,您需要具备以下软件和资源。* |
| |
| |=== |
| |软件或资源 |要求的版本 |
| |
| |link:http://download.netbeans.org/netbeans/7.1/beta/[+NetBeans IDE+] |7.2、7.3、7.4、8.0、Java EE 版本 |
| |
| |link:http://www.oracle.com/technetwork/java/javase/downloads/index.html[+Java 开发工具包 (JDK)+] |版本 7 或 8 |
| |
| |GlassFish Server Open Source Edition |3.1.x 或 4.x |
| |=== |
| |
| *先决条件* |
| |
| 本文档假定您具备以下技术的一些基本知识或编程经验: |
| |
| * Java 编程 |
| * NetBeans IDE |
| * Maven 框架 |
| |
| 在开始本教程之前,您可以先阅读下面这些文档。 |
| |
| * link:http://wiki.netbeans.org/MavenBestPractices[+NetBeans IDE 中的 Apache Maven 最佳做法+] |
| * link:http://books.sonatype.com/mvnref-book/reference/introduction.html[+Chapter 1. Introducing Apache Maven+](第 1 章. Apache Maven 简介,来自 link:http://books.sonatype.com/mvnref-book/reference/index.html[+Maven: The Complete Reference+](Maven:完整参考)) |
| * link:http://www.osgi.org/javadoc/r4v42/[+OSGi 框架+] |
| |
| |
| |
| |
| == 创建父 POM 项目 |
| |
| 在本节中,将为您要在本教程中创建的 OSGi 包创建父 POM 项目。此外,还将编辑项目 POM ( ``pom.xml`` ),以添加要作为依赖关系被子项目继承的依赖关系管理元素。 |
| |
| 1. 从主菜单中选择 "New Project"(新建项目)(Ctrl-Shift-N 组合键;在 Mac 中为 ⌘-Shift-N 组合键)。 |
| 2. 从 "Maven" 类别中选择 "POM Project"(POM 项目)。 |
| image::images/cdi-newpomproject.png[title="新建项目向导中 Maven POM 项目原型"] |
| 3. 键入 *MavenOSGiCDIProject* 作为项目名称。单击 "Finish"(完成)。 |
| |
| 单击 "Finish"(完成),此时 IDE 将创建 POM 项目并在 "Projects"(项目)窗口中打开该项目。 |
| |
| 4. 在 "Projects"(项目)窗口中展开 "Project Files"(项目文件)节点,然后双击 ``pom.xml`` 在编辑器中打开该文件。 |
| |
| 项目的基本 POM 应类似于以下内容。 |
| |
| |
| [source,xml] |
| ---- |
| |
| <?xml version="1.0" encoding="UTF-8"?> |
| <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| <modelVersion>4.0.0</modelVersion> |
| <groupId>com.mycompany</groupId> |
| <artifactId>MavenOSGiCDIProject</artifactId> |
| <version>1.0-SNAPSHOT</version> |
| <packaging>pom</packaging> |
| <properties> |
| <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
| </properties> |
| </project> |
| |
| ---- |
| 5. 修改父 ``pom.xml`` 以添加下列元素。保存所做的更改。 |
| |
| [source,xml] |
| ---- |
| |
| <?xml version="1.0" encoding="UTF-8"?> |
| <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| <modelVersion>4.0.0</modelVersion> |
| <groupId>com.mycompany</groupId> |
| <artifactId>MavenOSGiCDIProject</artifactId> |
| <version>1.0-SNAPSHOT</version> |
| <packaging>pom</packaging> |
| <properties> |
| <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
| </properties> |
| |
| *<dependencyManagement> |
| <dependencies> |
| <dependency> |
| <groupId>org.osgi</groupId> |
| <artifactId>org.osgi.core</artifactId> |
| <version>4.2.0</version> |
| <scope>provided</scope> |
| </dependency> |
| </dependencies> |
| </dependencyManagement>* |
| </project> |
| |
| ---- |
| |
| 在本练习中,您显式指定了要在项目中使用的工件和工件版本。通过使用依赖关系管理并在父 POM 中指定工件,可以使子项目中的 POM 更为简单,并确保依赖关系版本在项目中的一致性。 |
| |
| 有关使用依赖关系管理的详细信息,请参见link:http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html[+依赖关系机制简介+]。 |
| |
| |
| == 创建 OSGi 包项目 |
| |
| 新建项目向导中的 "Maven" 类别包含用于创建 OSGi 包项目的“OSGi 包”原型。创建 OSGi 包项目时,构建的 POM 声明 ``org.osgi.core`` JAR 作为附属项,并指定 ``maven-bundle-plugin`` 用于构建项目。 |
| |
| |
| === 创建 MavenHelloServiceApi 接口包 |
| |
| 在本练习中,将使用新建项目向导创建一个 OSGi 包项目,该项目将提供一个由其他包实现的简单接口。创建了包和接口后,将修改 POM 以更新对您在父 POM 项目中指定的 ``org.osgi.core`` 工件的依赖关系。 |
| |
| 1. 选择 "File"(文件)> "New Project"(新建项目)以打开新建项目向导。 |
| 2. 从 "Maven" 类别中选择 "OSGi Bundle"(OSGi 包)。单击 "Next"(下一步)。 |
| image::images/cdi-new-osgiproject.png[title="新建项目向导中的 Maven OSGi 包原型"] |
| 3. 键入 *MavenHelloServiceApi* 作为项目名称。 |
| 4. 单击 "Browse"(浏览),并选择 *MavenOSGiCDIProject* POM 项目作为位置。单击 "Finish"(完成)。 |
| |
| 单击 "Finish"(完成),此时 IDE 将创建包项目并在 "Projects"(项目)窗口中打开该项目。如果在编辑器中打开 MavenHelloServiceApi 项目的 ``pom.xml`` ,则可以看到 ``packaging`` 元素指定了 ``bundle`` 并且构建包时将使用 ``maven-bundle-plugin`` 。 |
| |
| |
| [source,xml] |
| ---- |
| |
| <project> |
| <modelVersion>4.0.0</modelVersion> |
| <parent> |
| <artifactId>MavenOSGiCDIProject</artifactId> |
| <groupId>com.mycompany</groupId> |
| <version>1.0-SNAPSHOT</version> |
| </parent> |
| |
| <groupId>com.mycompany</groupId> |
| <artifactId>MavenHelloServiceApi</artifactId> |
| <version>1.0-SNAPSHOT</version> |
| *<packaging>bundle</packaging>* |
| <name>MavenHelloServiceApi OSGi Bundle</name> |
| |
| <properties> |
| <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
| </properties> |
| |
| <dependencies> |
| <dependency> |
| <groupId>org.osgi</groupId> |
| <artifactId>org.osgi.core</artifactId> |
| <version>4.3.0</version> |
| <scope>provided</scope> |
| </dependency> |
| </dependencies> |
| |
| <build> |
| <plugins> |
| <plugin> |
| <groupId>org.apache.felix</groupId> |
| *<artifactId>maven-bundle-plugin</artifactId>* |
| <version>2.3.7</version> |
| <extensions>true</extensions> |
| <configuration> |
| <instructions> |
| <Bundle-Activator>com.mycompany.mavenhelloserviceimpl.Activator</Bundle-Activator> |
| <Export-Package /> |
| </instructions> |
| </configuration> |
| </plugin> |
| |
| ... |
| </plugins> |
| </build> |
| |
| ... |
| <project> |
| ---- |
| |
| 此外,您还可以看到,使用 Maven OSGi 包原型创建 OSGi 包项目时,IDE 在默认情况下将 ``org.osgi.core`` 工件添加为依赖关系。 |
| |
| 5. 在 "Projects"(项目)窗口中右键单击 "MavenHelloServiceApi" 项目节点,然后选择 "Properties"(属性)。 |
| 6. 在 "Project Properties"(项目属性)对话框中选择 "Sources"(源)类别。 |
| 7. 将 *Source/Binary Format*(源代码/二进制格式)设置为 "1.6",并确认 *Encoding*(编码)是 "UTF-8"。单击 "OK"(确定)。 |
| 8. 在 "Projects"(项目)窗口中右键单击 "Source Packages"(源包)节点,然后选择 "New"(新建)> "Java Interface"(Java 接口)。 |
| 9. 键入 *Hello* 作为类名。 |
| 10. 在 "Package"(包)中选择 *com.mycompany.mavenhelloserviceapi*。单击 "Finish"(完成)。 |
| 11. 将以下 ``sayHello`` 方法添加到接口中(以粗体显示),然后保存所做的更改。 |
| |
| [source,java] |
| ---- |
| |
| public interface Hello { |
| *String sayHello(String name);* |
| } |
| ---- |
| 12. 在 "Projects"(项目)窗口中右键单击项目节点,并选择 "Build"(构建)。 |
| |
| 构建项目后,如果打开 "Files"(文件)窗口,并展开项目节点,则可以看到在 ``target`` 文件夹中创建了 ``MavenHelloServiceApi-1.0-SNAPSHOT.jar`` 。 |
| |
| image::images/cdi-manifest.png[title="在 "Files"(文件)窗口中查看已编译 JAR 的内容"] |
| |
| 构建项目时, ``maven-bundle-plugin`` 将处理 ``MANIFEST.MF`` 文件的构建。如果打开已编译的 JAR 中的 ``MANIFEST.MF`` 文件,将看到此插件已生成一个清单标题,此标题声明了导出包。对于 OSGi,要公开并可供其他包使用的所有包都必须列在 ``MANIFEST.MF`` 的 ``Export-Package`` 元素中。 |
| |
| 13. 确认 ``MANIFEST.MF`` 包含 ``Export-Package`` 元素(以下示例中*粗体*显示的元素)。 |
| |
| [source,java] |
| ---- |
| |
| Manifest-Version: 1.0 |
| Bnd-LastModified: 1395049732676 |
| Build-Jdk: 1.7.0_45 |
| Built-By: nb |
| Bundle-Activator: com.mycompany.mavenhelloserviceapi.Activator |
| Bundle-ManifestVersion: 2 |
| Bundle-Name: MavenHelloServiceApi OSGi Bundle |
| Bundle-SymbolicName: com.mycompany.MavenHelloServiceApi |
| Bundle-Version: 1.0.0.SNAPSHOT |
| Created-By: Apache Maven Bundle Plugin |
| *Export-Package: com.mycompany.mavenhelloserviceapi;uses:="org.osgi.frame |
| work";version="1.0.0.SNAPSHOT"* |
| Import-Package: org.osgi.framework;version="[1.6,2)" |
| Tool: Bnd-1.50.0 |
| ---- |
| |
| OSGi 容器将读取 ``Export-Package`` 清单标题以确定可以从包外部访问此包中的类。在此示例中, ``com.mycompany.mavenhelloserviceapi`` 包中的类是公开的。 |
| |
| *注:*如果 ``MANIFEST.MF`` 不包含 ``Export-Package`` 元素,则您需要在 "Project Properties"(项目属性)窗口中启用插件的默认插件行为,并重新构建项目。在 "Project Properties"(项目属性)窗口中,选择 "Export Packages"(导出包)类别,然后选择 *Default maven-bundle-plugin behavior*(默认 maven-bundle-plugin 行为)选项。可以使用 "Project Properties"(项目属性)窗口的 "Export Packages"(导出包)面板显式指定应公开的包,或直接在 ``pom.xml`` 中指定包。 |
| |
| |
| |
| |
| === 创建 MavenHelloServiceImpl 实现包 |
| |
| 在本练习中,您将在 POM 项目中创建 MavenHelloServiceImpl。 |
| |
| 1. 选择 "File"(文件)> "New Project"(新建项目)以打开新建项目向导。 |
| 2. 从 "Maven" 类别中选择 "OSGi Bundle"(OSGi 包)。单击 "Next"(下一步)。 |
| 3. 键入 *MavenHelloServiceImpl* 作为项目名称。 |
| 4. 单击 "Browse"(浏览),并选择 *MavenOSGiCDIProject* POM 项目作为位置(如果未选择)。单击 "Finish"(完成)。 |
| 5. 右键单击 "Projects"(项目)窗口中的项目节点,然后选择 "Properties"(属性)。 |
| 6. 在 "Project Properties"(项目属性)对话框中选择 "Sources"(源)类别。 |
| 7. 将 *Source/Binary Format*(源代码/二进制格式)设置为 "1.6",并确认 *Encoding*(编码)是 "UTF-8"。单击 "OK"(确定)。 |
| 8. 在 "Projects"(项目)窗口中右键单击 "Source Packages"(源包)节点,然后选择 "New"(新建)> "Java Class"(Java 类)。 |
| 9. 键入 *HelloImpl* 作为类名。 |
| 10. 选择 *com.mycompany.mavenhelloserviceimpl* 作为包。单击 "Finish"(完成)。 |
| 11. 键入以下内容(以粗体显示),并保存所做的更改。 |
| |
| [source,java] |
| ---- |
| |
| public class HelloImpl *implements Hello { |
| |
| public String sayHello(String name) { |
| return "Hello " + name;* |
| } |
| } |
| ---- |
| |
| 实现 ``Hello`` 时,IDE 将显示一个错误,您需要将 MavenHelloServiceApi 项目添加为依赖关系才能解决该错误。 |
| |
| 12. 在 "Projects"(项目)窗口中右键单击 *MavenHelloServiceImpl* 的 "Dependencies"(依赖关系)节点,然后选择 "Add Dependency"(添加依赖关系)。 |
| 13. 在 "Add Library"(添加库)对话框中,单击 "Open Projects"(打开的项目)标签。 |
| 14. 选择 "MavenHelloServiceApi OSGi Bundle"(MavenHelloServiceApi OSGi 包)。单击 "ADD"(添加)。 |
| image::images/cdi-add-dependency.png[title="在 "Add Library"(添加库)对话框中打开 "Projects"(项目)标签"] |
| 15. 右键单击在编辑器中打开的 ``HelloImpl.java`` 类,然后选择 "Fix Imports"(修复导入)(Alt-Shift-I 组合键;在 Mac 上为 ⌘-Shift-I 组合键),以添加 ``com.mycompany.mavenhelloserviceapi.Hello`` 的 import 语句。保存所做的更改。 |
| 16. 展开 ``com.mycompany.mavenhelloserviceimpl`` 包并双击 ``Activator.java`` ,即可在编辑器中打开该文件。 |
| image::images/cdi-activator.png[title=""Projects"(项目)窗口中的激活器类"] |
| |
| IDE 在项目中自动创建了 ``Activator.java`` 包激活器类。包激活器用于管理包的生命周期。包激活器类在包的 ``MANIFEST.MF`` 中声明,并在容器启动该包时实例化。 |
| |
| OSGi 包不需要包激活器类,但可以使用激活器类中的 ``start()`` 方法,例如,用于初始化包所需的服务或其他资源。在此练习中将向类中添加一些代码行,将消息打印到 "Output"(输出)窗口。这将更便于确定包启动和停止的时间。 |
| |
| 17. 修改包激活器类中的 ``start()`` 和 ``stop()`` 方法,以添加下列行(以粗体显示)。 |
| |
| [source,java] |
| ---- |
| |
| public class Activator implements BundleActivator { |
| |
| public void start(BundleContext context) throws Exception { |
| *System.out.println("HelloActivator::start"); |
| context.registerService(Hello.class.getName(), new HelloImpl(), null); |
| System.out.println("HelloActivator::registration of Hello service successful");* |
| } |
| |
| public void stop(BundleContext context) throws Exception { |
| *context.ungetService(context.getServiceReference(Hello.class.getName())); |
| System.out.println("HelloActivator stopped");* |
| } |
| } |
| ---- |
| |
| 可以看到包激活器类导入了 ``org.osgi.framework.BundleActivator`` 和 ``org.osgi.framework.BundleContext`` 。默认情况下,生成的类包含两个方法: ``start()`` 和 ``stop()`` 。OSGi 框架调用 ``start()`` 和 ``stop()`` 方法来启动和停止包提供的功能。启动包时,包提供的服务组件会在 OSGi 服务注册表中进行注册。注册包之后,其他包可以使用注册表进行查找,然后通过包上下文使用活动服务。 |
| |
| 如果查看项目的 POM,则可以在 ``maven-bundle-plugin`` 的配置元素下方看到用于指定包激活器的 ``<Bundle-Activator>`` 元素。 |
| |
| |
| [source,xml] |
| ---- |
| |
| <plugin> |
| <groupId>org.apache.felix</groupId> |
| <artifactId>maven-bundle-plugin</artifactId> |
| <version>2.3.7</version> |
| <extensions>true</extensions> |
| <configuration> |
| <instructions> |
| *<Bundle-Activator>com.mycompany.mavenhelloserviceimpl.Activator</Bundle-Activator>* |
| </instructions> |
| </configuration> |
| </plugin> |
| ---- |
| |
| 在构建包时,该插件将在 JAR 的包清单文件中构建清单标题,并指定包激活器类。部署包时,OSGi 运行时在清单文件中查找 ``Bundle-Activator`` 标题。 |
| |
| 18. 在 ``Activator.java`` 中修复 import 语句,以导入 ``com.mycompany.mavenhelloserviceapi.Hello`` 。保存所做的更改。 |
| 19. 展开 "Dependencies"(依赖关系)节点,然后确认 ``org.osgi.core`` 工件作为依赖关系列出。 |
| |
| *注:*通过右键单击该工件并选择 "Remove Dependency"(移除依赖关系),移除 "Dependencies"(依赖关系)节点下列出的该工件的所有早期版本。唯一的依赖关系应是 MavenHelloServiceApi 项目和 ``org.osgi.core`` 工件。 |
| |
| image::images/cdi-implproject.png[title=""Projects"(项目)窗口中的激活器类"] |
| |
| |
| |
| === 构建和部署 OSGi 包 |
| |
| 在本练习中,将构建 OSGi 包,并将这些包部署到 GlassFish。 |
| |
| 1. 在 "Projects"(项目)窗口中,右键单击 "MavenOSGiCDIProject" 节点,然后选择 "Clean and Build"(清理并构建)。 |
| |
| 构建项目时,IDE 将在每个项目的 ``target`` 文件夹中创建 JAR 文件,还将在本地资源库中安装快照 JAR。在 "Files"(文件)窗口中,可以展开两个包项目中任一个的 ``target`` 文件夹,以查看两个 JAR 档案( ``MavenHelloServiceApi-1.0-SNAPSHOT.jar`` 和 ``MavenHelloServiceImpl-1.0-SNAPSHOT.jar`` )。 |
| |
| 2. 启动 GlassFish Server(如果尚未启动)。 |
| |
| 此时 "Output"(输出)窗口的 GlassFish Server 日志中应显示类似于以下内容的输出。 |
| |
| |
| [source,java] |
| ---- |
| |
| INFO: Started bundle: file:/glassfish-4.0/glassfish/domains/domain1/autodeploy/bundles/MavenHelloServiceApi-1.0-SNAPSHOT.jar |
| |
| ---- |
| |
| 在 "Services"(服务)窗口中右键单击 "GlassFish Server" 节点,然后选择 "View Domain Server Log"(查看域服务器日志)(如果 "Output"(输出)窗口中不显示服务器日志)。 |
| |
| 4. 重复执行相关步骤,将 ``MavenHelloServiceImpl-1.0-SNAPSHOT.jar`` 复制到 ``autodeploy/bundles`` 目录。 |
| |
| 现在,GlassFish Server 日志中应显示类似于以下内容的输出。 |
| |
| |
| [source,java] |
| ---- |
| |
| INFO: HelloActivator::start |
| INFO: HelloActivator::registration of Hello service successful |
| INFO: Started bundle: file:/glassfish-4.0/glassfish/domains/domain1/autodeploy/bundles/MavenHelloServiceImpl-1.0-SNAPSHOT.jar |
| INFO: Started bundle: file:/glassfish-4.0/glassfish/domains/domain1/autodeploy/bundles/MavenHelloServiceImpl-1.0-SNAPSHOT.jar |
| |
| ---- |
| |
| 或者,也可以从 GlassFish OSGi 管理控制台安装包。有关详细信息,请参见<<Exercise_4,安装和使用 OSGi 管理控制台>>部分。 |
| |
| |
| == 创建 Web 客户端应用程序 |
| |
| 此部分演示如何创建访问 OSGi 包提供的服务的 Java EE Web 客户端。将在 Web 应用程序中创建一个简单 Servlet,然后注入声明的服务。创建项目前,将向父 POM 项目中添加一些依赖关系管理元素。 |
| |
| |
| === 在父 POM 项目中配置依赖关系 |
| |
| 在本练习中,将指定父 POM 项目中的依赖关系元素。此外,还将添加项目要使用的工件的资源库。 |
| |
| 1. 在 "Projects"(项目)窗口中展开 *MavenOSGiCDIProject* 项目的 "Project Files"(项目文件)节点,然后双击 ``pom.xml`` 在编辑器中打开该文件。 |
| 2. 修改父 ``pom.xml`` 以添加下列依赖关系管理元素(以粗体显示)。保存所做的更改。 |
| |
| [source,xml] |
| ---- |
| |
| <?xml version="1.0" encoding="UTF-8"?> |
| <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| <modelVersion>4.0.0</modelVersion> |
| <groupId>com.mycompany</groupId> |
| <artifactId>MavenOSGiCDIProject</artifactId> |
| <version>1.0-SNAPSHOT</version> |
| <packaging>pom</packaging> |
| <properties> |
| <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
| </properties> |
| |
| ... |
| |
| <dependencyManagement> |
| <dependencies> |
| <dependency> |
| <groupId>org.osgi</groupId> |
| <artifactId>org.osgi.core</artifactId> |
| <version>4.3.0</version> |
| <scope>provided</scope> |
| </dependency> |
| *<dependency> |
| <groupId>org.osgi</groupId> |
| <artifactId>org.osgi.compendium</artifactId> |
| <version>4.2.0</version> |
| <scope>provided</scope> |
| </dependency> |
| <dependency> |
| <groupId>org.glassfish</groupId> |
| <artifactId>osgi-cdi-api</artifactId> |
| <version>3.1-b41</version> |
| <type>jar</type> |
| <scope>provided</scope> |
| </dependency>* |
| |
| </dependencies> |
| </dependencyManagement> |
| |
| ... |
| </project> |
| |
| ---- |
| 3. 添加下列元素,将 GlassFish 资源库添加到 POM 中。保存所做的更改。 |
| |
| [source,xml] |
| ---- |
| |
| <project> |
| |
| ... |
| |
| </dependencyManagement> |
| |
| *<repositories> |
| <!-- glassfish nexus repo for glassfish dependencies --> |
| <repository> |
| <id>glassfish-repo-archive</id> |
| <name>Nexus repository collection for Glassfish</name> |
| <url>http://maven.glassfish.org/content/groups/glassfish</url> |
| <snapshots> |
| <updatePolicy>never</updatePolicy> |
| </snapshots> |
| </repository> |
| </repositories>* |
| <modules> |
| <module>MavenHelloServiceApi</module> |
| <module>MavenHelloServiceImpl</module> |
| </modules> |
| </project> |
| |
| ---- |
| |
| 将 GlassFish 资源库添加到 POM 后,如果在 "Services"(服务)窗口中查看 "Maven Repositories"(Maven 资源库)节点下的资源库列表,将会看到 IDE 为 GlassFish 资源库自动添加了一个节点。默认情况下,IDE 会为本地 Maven 资源库显示一个节点。在打开的项目指定资源库时,IDE 将在 "Maven Repositories"(Maven 资源库)节点下为该资源库自动添加一个节点。 |
| |
| image::images/cdi-maven-repositories.png[title=""Maven Repositories"(Maven 资源库)窗口中的 GlassFish 资源库"] |
| |
| 在本练习中,您添加了其他要在项目中使用的工件和工件版本。此外,您还添加了包含 ``osgi-cdi-api`` 工件的 GlassFish 资源库。 |
| |
| |
| === 创建 MavenHelloWebClient Web 应用程序 |
| |
| 首先,将创建常规的 Web 应用程序,然后修改项目将其作为 OSGi 包(Web 应用程序包 (WAB))。 |
| |
| 1. 从主菜单中选择 "File"(文件)> "New Project"(新建项目)。 |
| 2. 从 "Maven" 类别中选择 "Web Application"(Web 应用程序)。单击 "Next"(下一步)。 |
| 3. 键入 *MavenHelloWebClient* 作为项目名称。 |
| 4. 单击 "Browse"(浏览),并选择 *MavenOSGiCDIProject* POM 项目作为位置(如果尚未选择)。单击 "Next"(下一步)。 |
| 5. 选择 "GlassFish Server" 作为服务器,并选择 "Java EE 6 Web" 或 "Java EE 7 Web" 作为 Java EE 版本。单击 "Finish"(完成)。 |
| 6. 右键单击项目节点,然后选择 "New"(新建)> "Servlet"。 |
| 7. 键入 *HelloServlet* 作为类名。 |
| 8. 选择 ``com.mycompany.mavenhellowebclient`` 作为包。单击 "Finish"(完成)。 |
| 9. 删除 Servlet 中已由 IDE 生成的默认方法( ``processRequest`` 、 ``doGet`` 、 ``doPost`` 、 ``getServletInfo`` )。 |
| |
| *注:*需要展开编辑器折叠才能删除 HttpServlet 方法。 |
| |
| 10. 键入以下将注入服务的代码(以粗体显示)。 |
| |
| [source,java] |
| ---- |
| |
| @WebServlet(name = "HelloServlet", urlPatterns = {"/HelloServlet"}) |
| public class HelloServlet extends HttpServlet { |
| |
| *@Inject |
| @OSGiService(dynamic=true) |
| Hello hello;* |
| } |
| ---- |
| 11. 添加以下 ``doGet`` 方法。 |
| |
| [source,java] |
| ---- |
| |
| @Override |
| protected void doGet(HttpServletRequest request, HttpServletResponse response) |
| throws ServletException, IOException { |
| PrintWriter out = response.getWriter(); |
| out.println(hello.sayHello("Duke")); |
| } |
| ---- |
| 12. 右键单击项目节点,然后选择 "New"(新建)> "Other"(其他)。 |
| 13. 在 "Contexts and Dependency Injection"(上下文和依赖关系注入)类别中选择 *beans.xml*。单击 "Next"(下一步)。 |
| 14. 使用默认文件名 ( ``beans`` )。单击 "Finish"(完成)。 |
| |
| 单击 "Finish"(完成),此时该向导将在 Web 应用程序中创建 ``beans.xml`` 文件。如果 ``beans.xml`` 是该应用程序的一部分,则系统将自动启用 CDI。 |
| |
| 15. 修改 ``beans.xml`` 文件以将 ``bean-discovery-mode`` 的默认值更改为 ``all`` 。 |
| |
| [source,java] |
| ---- |
| |
| bean-discovery-mode="*all*" |
| ---- |
| |
| 保存更改并关闭文件。 |
| |
| 有关 ``bean-discovery-mode`` 值之间的差异的详细信息,请参见以下页: |
| |
| * Java EE 7 教程中的 link:http://docs.oracle.com/javaee/7/tutorial/doc/cdi-adv001.htm[+25.1:打包 CDI 应用程序+] |
| * link:http://stackoverflow.com/questions/18107858/cdi-inject-fails-on-maven-embedded-glassfish-plugin-org-jboss-weld-exceptions[+http://stackoverflow.com/questions/18107858/cdi-inject-fails-on-maven-embedded-glassfish-plugin-org-jboss-weld-exceptions+] |
| 16. 在 "Projects"(项目)窗口中右键单击 "MavenHelloWebClient" 的 "Dependencies"(依赖关系)节点,然后选择 "Add Dependency"(添加依赖关系)。 |
| 17. 选择 *Provided* 作为作用域。 |
| 18. 在 "Add Library"(添加库)对话框中单击 "Open Projects"(打开的项目)标签,然后选择 *MavenHelloServiceApi OSGi Bundle(MavenHelloServiceApi OSGi 包)*。单击 "ADD"(添加)。 |
| 19. 再次右键单击 "Dependencies"(依赖关系)节点,然后选择 "Add Dependency"(添加依赖关系)。 |
| 20. 在 "Add Library"(添加库)对话框中单击 "Dependency Management"(依赖关系管理)标签,然后选择在父 POM 项目中指定的 ``osgi-cdi-api`` 工件。单击 "ADD"(添加)。 |
| image::images/cdi-add-dependency3.png[title=""Add Library"(添加库)对话框中的 "Dependency Management"(依赖关系管理)标签"] |
| 21. 在编辑器中右键单击 ``HelloServlet.java`` ,然后选择 "Fix Imports"(修复导入)(Alt-Shift-I 组合键;在 Mac 上为 ⌘-Shift-I 组合键),以添加 ``com.mycompany.mavenhelloserviceapi.Hello`` 、 ``javax.inject.Inject`` 和 ``org.glassfish.osgicdi.OSGiService`` 。保存所做的更改。 |
| |
| *注:*如果 IDE 未自动添加 ``com.mycompany.mavenhelloserviceapi.Hello`` 的 import 语句,则可能需要手动进行添加。 |
| |
| 22. 右键单击 "MavenOSGiCDIProject",然后选择 "Clean and Build"(清理并构建)。 |
| |
| 构建项目时,"Output"(输出)窗口中应显示类似于以下内容的输出。 |
| |
| |
| [source,java] |
| ---- |
| |
| Reactor Summary: |
| |
| MavenOSGiCDIProject ............................... SUCCESS [0.798s] |
| MavenHelloServiceApi OSGi Bundle .................. SUCCESS [7.580s] |
| MavenHelloServiceImpl OSGi Bundle ................. SUCCESS [1.142s] |
| MavenHelloWebClient ............................... SUCCESS [8.072s] |
| ------------------------------------------------------------------------ |
| BUILD SUCCESS |
| ---- |
| |
| *注:*如果在构建 MavenOSGiCDIProject 项目时未自动构建 Web 应用程序,则您需要手动构建 Web 应用程序。 |
| |
| 在 "Files"(文件)窗口中,展开 Web 应用程序的项目节点,并确认在目标目录中创建了档案 ``MavenHelloWebClient-1.0-SNAPSHOT.war`` 。如果展开 Web 客户端的 WAR 档案并检查 ``MANIFEST.MF`` ,则会看到清单中包含类似于以下内容的行。 |
| |
| |
| [source,java] |
| ---- |
| |
| Manifest-Version: 1.0 |
| Archiver-Version: Plexus Archiver |
| Created-By: Apache Maven |
| Built-By: nb |
| Build-Jdk: 1.7.0_45 |
| ---- |
| |
| |
| === 以 OSGi 包的形式构建 Web 应用程序 |
| |
| 要使用 ``@OSGiService`` 并检索已注册的 OSGi 包,您需要将 Web 应用程序作为可访问 ``BundleContext`` 的包。要使 WAR 成为 OSGi 包(Web 应用程序包),可将 ``Web-ContextPath`` 元数据添加到 WAR 中的 ``MANIFEST.MF`` 。 要执行此操作,请在 ``maven-bundle-plugin`` 的说明中指定 ``<Web-ContextPath>`` 元素,该元素将包含在由插件生成的清单中。然后,修改 ``maven-war-plugin`` 配置,以指示插件将 ``maven-bundle-plugin`` 生成的清单添加到 WAR 档案中。 |
| |
| 1. 在 "Projects"(项目)窗口中,展开 "MavenHelloWebClient" 下方的 "Project Files"(项目文件)节点,然后双击 ``pom.xml`` 在编辑器中打开该文件。 |
| 2. 添加以下条目,将 ``maven-bundle-plugin`` 添加到 POM 中。 |
| |
| [source,xml] |
| ---- |
| |
| <build> |
| <plugins> |
| *<plugin> |
| <groupId>org.apache.felix</groupId> |
| <artifactId>maven-bundle-plugin</artifactId> |
| <version>2.2.0</version> |
| <extensions>true</extensions> |
| <configuration> |
| <supportedProjectTypes> |
| <supportedProjectType>ejb</supportedProjectType> |
| <supportedProjectType>war</supportedProjectType> |
| <supportedProjectType>bundle</supportedProjectType> |
| <supportedProjectType>jar</supportedProjectType> |
| </supportedProjectTypes> |
| <instructions> |
| <!-- Specify elements to add to MANIFEST.MF --> |
| <Web-ContextPath>/mavenhellowebclient</Web-ContextPath> |
| <!-- By default, nothing is exported --> |
| <Export-Package>!*.impl.*, *</Export-Package> |
| </instructions> |
| </configuration> |
| <executions> |
| <execution> |
| <id>bundle-manifest</id> |
| <phase>process-classes</phase> |
| <goals> |
| <goal>manifest</goal> |
| </goals> |
| </execution> |
| <execution> |
| <id>bundle-install</id> |
| <phase>install</phase> |
| <goals> |
| <goal>install</goal> |
| </goals> |
| </execution> |
| </executions> |
| </plugin>* |
| |
| ---- |
| 3. 修改 ``maven-war-plugin`` 的配置元素,将包信息添加到 ``MANIFEST.MF`` 中。保存所做的更改。 |
| |
| [source,xml] |
| ---- |
| |
| <plugin> |
| <groupId>org.apache.maven.plugins</groupId> |
| <artifactId>maven-war-plugin</artifactId> |
| <version>2.3</version> |
| <configuration> |
| *<archive> |
| <!-- add bundle plugin generated manifest to the war --> |
| <manifestFile> |
| ${project.build.outputDirectory}/META-INF/MANIFEST.MF |
| </manifestFile> |
| <!-- For some reason, adding Bundle-ClassPath in maven-bundle-plugin |
| confuses that plugin and it generates wrong Import-Package, etc. |
| So, we generate it here.--> |
| <manifestEntries> |
| <Bundle-ClassPath>WEB-INF/classes/</Bundle-ClassPath> |
| </manifestEntries> |
| </archive>* |
| <failOnMissingWebXml>false</failOnMissingWebXml> |
| </configuration> |
| </plugin> |
| ---- |
| 4. 在 "Projects"(项目)窗口中,右键单击 "MavenHelloWebClient" 项目节点,然后选择 "Clean and Build"(清理并构建)。 |
| |
| 如果您现在展开 WAR 档案,并在编辑器中打开 ``MANIFEST.MF`` ,则会看到 ``MANIFEST.MF`` 现在包含其他信息,包括您在 ``maven-bundle-plugin`` 配置和包名称条目中指定的 ``Web-ContextPath: /mavenhellowebclient`` 条目。 |
| |
| |
| [source,java] |
| ---- |
| |
| Manifest-Version: 1.0 |
| Export-Package: com.mycompany.mavenhellowebclient;uses:="com.mycompany |
| .mavenhelloserviceapi,javax.servlet,org.glassfish.osgicdi,javax.injec |
| t,javax.servlet.annotation,javax.servlet.http";version="1.0.0.SNAPSHO |
| T" |
| Bundle-ClassPath: WEB-INF/classes/ |
| Built-By: nb |
| Tool: Bnd-1.50.0 |
| Bundle-Name: MavenHelloWebClient |
| Created-By: Apache Maven Bundle Plugin |
| *Web-ContextPath: /mavenhellowebclient* |
| Build-Jdk: 1.7.0_45 |
| Bundle-Version: 1.0.0.SNAPSHOT |
| Bnd-LastModified: 1395053424008 |
| Bundle-ManifestVersion: 2 |
| Import-Package: com.mycompany.mavenhelloserviceapi;version="[1.0,2)",j |
| avax.inject,javax.servlet,javax.servlet.annotation,javax.servlet.http |
| ,org.glassfish.osgicdi;version="[1.0,2)" |
| Bundle-SymbolicName: com.mycompany.MavenHelloWebClient |
| Archiver-Version: Plexus Archiver |
| ---- |
| |
| 有关如何以 OSGi 包的形式构建 Web 应用程序的详细信息,请参见以下页。 |
| |
| * link:http://weblogs.java.net/blog/2009/06/04/osgi-enabled-web-applications-inglassfish[+http://weblogs.java.net/blog/2009/06/04/osgi-enabled-web-applications-inglassfish+] |
| * link:http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html[+http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html+] |
| |
| |
| === 部署 Web 应用程序包 |
| |
| 在本练习中,您需要将 Web 应用程序包复制到 GlassFish 安装中的 ``autodeploy/bundles`` 文件夹。 |
| |
| 1. 导航至包含 ``MavenHelloWebClient-1.0-SNAPSHOT.war`` 的 ``target`` 目录。 |
| 2. 将 ``MavenHelloWebClient-1.0-SNAPSHOT.war`` 复制到 GlassFish 安装的 ``autodeploy/bundles`` 文件夹中。 |
| |
| 将 WAR 档案复制到目录时,GlassFish Server 日志中将显示类似于以下内容的输出。 |
| |
| |
| [source,java] |
| ---- |
| |
| INFO: Started bundle: file:/glassfish-3.1.1/glassfish/domains/domain1/autodeploy/bundles/MavenHelloWebClient-1.0-SNAPSHOT.war |
| ... |
| INFO: ---- Injection requested for framework service type interface com.mycompany.mavenhelloserviceapi.Hello and annotated with dynamic=true, serviceCriteria= |
| INFO: WEB0671: Loading application [com.mycompany.MavenHelloWebClient_1.0.0.SNAPSHOT] at [/mavenhellowebclient] |
| INFO: Registered ServletContext as a service with properties: {osgi.web.symbolicname=com.mycompany.MavenHelloWebClient, osgi.web.version=1.0.0.SNAPSHOT, osgi.web.contextpath=/mavenhellowebclient} |
| |
| ---- |
| |
| 现在,您可以通过单击以下链接 link:http://localhost:8080/mavenhellowebclient/HelloServlet[+http://localhost:8080/mavenhellowebclient/HelloServlet+] 在浏览器中查看 Servlet。 |
| |
| |
| == 安装和使用 OSGi 管理控制台 |
| |
| 您可以使用 GlassFish OSGi 管理控制台来安装、启动和停止部署到服务器上的 OSGi 包。在本练习中,将启用 GlassFish OSGi 管理控制台,然后查看已注册的 OSGi 包列表。 |
| |
| 执行以下步骤安装所需的 GlassFish 附件以启用 OSGi 控制台,并查看 GlassFish 域管理控制台中的已部署包。 |
| |
| 1. 在浏览器中打开 GlassFish 域管理控制台。 |
| |
| 在 "Services"(服务)窗口中,右键单击 "GlassFish Server" 节点,然后选择 "View Domain Admin Console"(查看域管理控制台)。 |
| |
| 2. 单击左侧导航栏中的 "Update Tool"(更新工具)。 |
| 3. 从可用附件列表中选择 ``glassfish-osgi-gui`` 。 |
| |
| 单击 "Install"(安装),然后接受许可证。 |
| |
| image::images/cdi-glassfish-addons.png[title="GlassFish 管理控制台的 "Update Tool"(更新工具)"] |
| 4. 重新启动 GlassFish Server。 |
| |
| *重要说明:*如果您运行的是 GlassFish Server 3.1.2.2,则需要修改位于 ``_GLASSFISH-INSTALL_/glassfish/config/`` 目录中的 ``osgi.properties`` 文件,并将 ``org.osgi.framework.startlevel.beginning`` 属性的值设置为 "2" ( ``org.osgi.framework.startlevel.beginning=2`` )。 |
| 有关更多详细信息,请参见以下论坛帖子: |
| link:http://www.java.net/forum/topic/glassfish/glassfish/cannot-start-web-console-glassfish-version-3122[+ 无法在 Glassfish 3.1.2.2 版中启动 Web 控制台+]。 |
| |
| 5. 再次打开管理控制台,然后在左侧的导航栏中单击 *Server (Admin Server)*(服务器(管理服务器))。 |
| 6. 单击 "OSGi Console"(OSGi 控制台)标签,以查看已部署的 OSGi 包列表。 |
| image::images/cdi-glassfish-console.png[title=""Add Library"(添加库)对话框中的 "Dependency Management"(依赖关系管理)标签"] |
| |
| *注:*系统可能会提示您输入用户名和口令来查看 OSGi 包列表。如果您在 "OSGi Console"(OSGi 控制台)标签中看不到包列表,请确认未隐藏授权对话框。如果您在安装 IDE 时安装了 GlassFish 4 Server,则此服务器的默认用户名为 ``admin`` 。默认情况下口令为空。 |
| |
| 您可以向下滚动列表,以查看已注册的 OSGi 包的状态,并启动和停止各个包。如果按 ID 对列表进行排序(从高到低),则会看到已部署的三个包显示在该列表的顶部附近。 |
| |
| |
| link:/about/contact_form.html?to=3&subject=Feedback:%20Using%20CDI%20to%20Inject%20OSGi%20Bundles%20as%20Services[+发送有关此教程的反馈意见+] |
| |
| |
| |
| == 另请参见 |
| |
| 有关使用 NetBeans IDE 和 Maven 开发 OSGi 包的更多信息,请参见以下资源: |
| |
| * link:http://wiki.netbeans.org/OSGiAndNetBeans[+wiki.netbeans.org 上的 OSGi 和 NetBeans+] |
| * link:http://wiki.netbeans.org/MavenBestPractices[+NetBeans IDE 中的 Apache Maven 最佳做法+] |
| * link:https://blogs.oracle.com/arungupta/entry/totd_125_creating_an_osgi[+TOTD #125:使用 NetBeans 创建一个 OSGi 包,并在 GlassFish 中部署+] |
| * link:../../trails/java-ee.html[+Java EE 和 Java Web 学习资源+] |
| |
| 要发送意见和建议、获得支持以及随时了解 NetBeans IDE Java EE 开发功能的最新开发情况,请link:../../../community/lists/top.html[+加入 nbj2ee 邮件列表+]。 |
| |