CQ 的构建基于
OSGi 容器,所以自定义的代码和功能能够通过 OSGi 提供的 feature 添加到 CQ。要将自定义的代码部署到 OSGi 容器,开发者必须将他们的代码作为一个 bundle 进行打包。一个 OSGi bundle 只是一个添加了额外元数据的 jar 文件。本文将详细介绍如何使用 Apache Maven 来创建一个 OSGi bundle,以及如何将该 bundle 部署到一个正在运行的 CQ 实例中去。
这个插件允许开发者处理起来就像使用 Maven (通过命令行或者一个 IDE 工具)创建一个基本的 jar 文件那样,但却可以提供对添加到 bundle 中的 OSGi 元数据进行低级别的控制。
第一步是创建一个新的 Maven 项目,将打包样式设置为 bundle,当然还有添加 Apache Felix Bundle 插件的定义。
下一步是对 Apache Felix Bundle 插件进行配置:
以上例子设置了以下几个配置项:
<Bundle-Activator>
OSGi Bundle Activator (绑定到 OSGi bundle 生命周期的一个类,通过它我们可以在诸如 bundle 启动或者关闭的时候执行自定义的代码)的完整的 Java 类名。这一设置是可选的。
<Private-Package>
不应该暴露给 OSGi 容器的包(比如只包含有实现类而非 bundle 所提供 API 相关功能的一些包)。上面的例子将 Activator 所在的包声明为 private。
<Embed-Dependency>
在创建 bundle 时要嵌入哪些 Maven 依赖。上述例子中设置为 *;scope=compile|runtime 是因为将要包含 scope 为 compile 或 runtime 的所有依赖,这些将成为 bundle 正常运行所需要的所有的类。
建议在你的 bundle 里加入这个依赖项配置。替代方法就是不必在 bundle 里嵌入依赖项,而是从 OSGi 容器中导入依赖项。 我们推荐前者,因为它使其他开发人员能够更轻松地使用 bundle,而不必去追溯所有的依赖并在部署新 bundle 时将他们先部署进来。
任何在 bundle 编译时需要而在运行时由 OSGi 容器所提供的依赖(举个例子, org.osgi.framework 包里的所有的类)应该进行 scope 为 provided 的声明 - 这样它们就不会被嵌入进 bundle 里去了。
<Embed-Directory>
嵌入的第三方包将会放在该 bundle 中的位置。将其设置为 OSGI-INF/lib。OSGI-INF 目录是 OSGi 相关的其它元数据将要放置的地方,这个也模仿自大多数 Java 开发者所熟悉的 WEB-INF/lib 目录。
<Embed-Transitive>
是否只嵌入该 bundle pom 的直接依赖(要嵌入的话将其设置为 false),或者是否还要嵌入 pom 所声明的依赖关系的传递图 (要嵌入的话将其设置为 true)。将此项设置为 true,因为这将会让我们更加容易地去处理该 bundle。如果有一些不应该包含进来的依赖(比如可能有其它 bundle 将它们设置成了对整个项目都可见,结果就是 - 包冲突),可以使用 Embed-Dependency 标签将它们给过滤掉。
<Import-Package>
该 bundle 所需要的由 OSGi 容器所提供的包(比如,bundle 自身需要的自己却没有嵌入的一些类)。由于使用缺省值就足够了,这个标签通常会被忽略。最终值将不仅包含 bundle 代码中所需要的包,而且还包括由已嵌入的任何依赖项所需要的包。如果该 bundle 导入的某个类没有在 OSGi 容器中提供,该 bundle 仍然能够被安装,但却无法被启动。
bundle 的创建成功之后,所需要的OSGi 元数据将被添加到该 jar 的 MANFIFEST.MF 文件,而且所有的依赖也会被嵌入到了 OSGI-INF/lib 目录中。
更多关于这些以及其它选项的详细信息请参见 Apache Felix Bundle 插件页面。
由于 CQ 的构建基于 Apache Sling,我们可以使用该项目的一个 Maven 插件将 OSGi bundle 直接部署到 CQ。 Maven Sling 插件使我们能够将一个 OSGi bundle 部署到一个本地或远程运行中的 CQ 实例中去。
接下来,在该 POM 中添加一个新的 profile,在该 profile 中添加一个插件的定义以启用 Maven Sling 插件。
在一个 profile 里声明 Sling 插件并且对于该 profile 默认不激活,这很重要,这是因为如果不能连接到指定的 CQ 实例的话 Sing 插件将会导致 Maven 构建失败。通过将 Sling 插件丢到一个 profile 里,Maven 将能够构建并发布 bundle,而无需有一个可用的正在运行的 CQ 实例。
尽管如此,在重部署环境下,只需简单激活这个 auto-deploy profile,然后每次在运行 Maven install 时 ,该 bundle 将会被自动重新部署到 CQ。命令行示例如下所示:
mvn -Pauto-deploy clean install
大多数常见的 IDE (Eclipse,NetBeans 等等) 都允许开发者在执行 Maven 构建的时候配置哪些 profile 是可用的。
通过 Maven properties 的使用将 Sling 的连接配置进行参数化也很重要,这样构建就可以轻松地在多个开发者的机器上执行,但在 POM 中还是要提供默认值。
当默认值不可用的时候,可以使用标准 Maven 功能对它们进行轻松重写。对服务器 URL 进行命令行一次性构建重写的示例如下:
mvn -Pauto-deploy -Dcrx.url=http://localhost:8080 clean install
或者进行更永久化的重写,将该 property 直接添加到用户的 settings.xml 文件:
Maven 构建执行之后,如果部署成功,该 bundle 将会被安装并启动。取决于该 bundle 所做的事情,任何负面影响应该可以立即看到。最后,该 bundle 将会在管理员控制台的 Bundles 屏幕中列出,默认位置是:
http://localhost:4502/system/console/bundles
原文链接: Building & Deploying OSGi Bundles。
作者简介
CQBlueprints 网站旨在能够对使用 Adobe CQ 的架构师和开发人员提供一些帮助。尽管在 Adobe 的官方网站上已经有了很多关于 CQ 的相关信息,但是那些信息主要专注于 CQ 自身的产品。当你真正去落地 CQ 的时候你还得去考虑很多额外的课题(诸如,如何自主开发?开发的东西如何才能在部署环境下工作?)。 CQBlueprints 网站针对的正是这些问题。
构建一个 OSGi bundle
对于一名 CQ 开发者来说要构建一个 OSGi bundle 最简单的办法就是通过 Apache Felix Bundle 插件使用 Apache Maven。这一插件由 Apache Felix 团队基于 Peter Kriens 的 BND 工具所开发,尽管如此,它所创建的 OSGi bundle 并不只是针对于 Felix,它同样可以为其它 OSGi 容器所用。这个插件允许开发者处理起来就像使用 Maven (通过命令行或者一个 IDE 工具)创建一个基本的 jar 文件那样,但却可以提供对添加到 bundle 中的 OSGi 元数据进行低级别的控制。
第一步是创建一个新的 Maven 项目,将打包样式设置为 bundle,当然还有添加 Apache Felix Bundle 插件的定义。
<?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>
<parent>
<groupId>com.headwire.cqblueprints</groupId>
<artifactId>parent</artifactId>
<version>5.4.0-SNAPSHOT</version>
</parent>
<artifactId>cqblueprints-examples-osgi-bundle</artifactId>
<packaging>bundle</packaging>
...
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.3.5</version>
<extensions>true</extensions>
</plugin>
...
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
...
</plugin>
</plugins>
</build>
...
</project>
下一步是对 Apache Felix Bundle 插件进行配置:
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
<Bundle-Activator>com.headwire.cqblueprints.examples.osgi.Activator</Bundle-Activator>
<Private-Package>com.headwire.cqblueprints.examples.osgi</Private-Package>
<Embed-Dependency>*;scope=compile|runtime</Embed-Dependency>
<Embed-Directory>OSGI-INF/lib</Embed-Directory>
<Embed-Transitive>true</Embed-Transitive>
<Import-Package>!org.slf4j.impl,*</Import-Package>
</instructions>
</configuration>
</plugin>
以上例子设置了以下几个配置项:
<Bundle-Activator>
OSGi Bundle Activator (绑定到 OSGi bundle 生命周期的一个类,通过它我们可以在诸如 bundle 启动或者关闭的时候执行自定义的代码)的完整的 Java 类名。这一设置是可选的。
<Private-Package>
不应该暴露给 OSGi 容器的包(比如只包含有实现类而非 bundle 所提供 API 相关功能的一些包)。上面的例子将 Activator 所在的包声明为 private。
<Embed-Dependency>
在创建 bundle 时要嵌入哪些 Maven 依赖。上述例子中设置为 *;scope=compile|runtime 是因为将要包含 scope 为 compile 或 runtime 的所有依赖,这些将成为 bundle 正常运行所需要的所有的类。
建议在你的 bundle 里加入这个依赖项配置。替代方法就是不必在 bundle 里嵌入依赖项,而是从 OSGi 容器中导入依赖项。 我们推荐前者,因为它使其他开发人员能够更轻松地使用 bundle,而不必去追溯所有的依赖并在部署新 bundle 时将他们先部署进来。
任何在 bundle 编译时需要而在运行时由 OSGi 容器所提供的依赖(举个例子, org.osgi.framework 包里的所有的类)应该进行 scope 为 provided 的声明 - 这样它们就不会被嵌入进 bundle 里去了。
<Embed-Directory>
嵌入的第三方包将会放在该 bundle 中的位置。将其设置为 OSGI-INF/lib。OSGI-INF 目录是 OSGi 相关的其它元数据将要放置的地方,这个也模仿自大多数 Java 开发者所熟悉的 WEB-INF/lib 目录。
<Embed-Transitive>
是否只嵌入该 bundle pom 的直接依赖(要嵌入的话将其设置为 false),或者是否还要嵌入 pom 所声明的依赖关系的传递图 (要嵌入的话将其设置为 true)。将此项设置为 true,因为这将会让我们更加容易地去处理该 bundle。如果有一些不应该包含进来的依赖(比如可能有其它 bundle 将它们设置成了对整个项目都可见,结果就是 - 包冲突),可以使用 Embed-Dependency 标签将它们给过滤掉。
<Import-Package>
该 bundle 所需要的由 OSGi 容器所提供的包(比如,bundle 自身需要的自己却没有嵌入的一些类)。由于使用缺省值就足够了,这个标签通常会被忽略。最终值将不仅包含 bundle 代码中所需要的包,而且还包括由已嵌入的任何依赖项所需要的包。如果该 bundle 导入的某个类没有在 OSGi 容器中提供,该 bundle 仍然能够被安装,但却无法被启动。
bundle 的创建成功之后,所需要的OSGi 元数据将被添加到该 jar 的 MANFIFEST.MF 文件,而且所有的依赖也会被嵌入到了 OSGI-INF/lib 目录中。
更多关于这些以及其它选项的详细信息请参见 Apache Felix Bundle 插件页面。
部署一个 OSGi bundle
创建 OSGi bundle 的 Maven POM 配置好以后,接下来还要为部署该 bundle 到一个运行中的 CQ 环境对其进行继续配置。由于 CQ 的构建基于 Apache Sling,我们可以使用该项目的一个 Maven 插件将 OSGi bundle 直接部署到 CQ。 Maven Sling 插件使我们能够将一个 OSGi bundle 部署到一个本地或远程运行中的 CQ 实例中去。
接下来,在该 POM 中添加一个新的 profile,在该 profile 中添加一个插件的定义以启用 Maven Sling 插件。
<profiles>
<profile>
<id>auto-deploy</id>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.sling</groupId>
<artifactId>maven-sling-plugin</artifactId>
<version>2.0.4-incubator</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.sling</groupId>
<artifactId>maven-sling-plugin</artifactId>
<executions>
<execution>
<id>deploy-to-cq</id>
<phase>install</phase>
<goals>
<goal>install</goal>
</goals>
<configuration>
<slingUrl>${crx.url}/system/console/install</slingUrl>
<user>${crx.user}</user>
<password>${crx.password}</password>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
在一个 profile 里声明 Sling 插件并且对于该 profile 默认不激活,这很重要,这是因为如果不能连接到指定的 CQ 实例的话 Sing 插件将会导致 Maven 构建失败。通过将 Sling 插件丢到一个 profile 里,Maven 将能够构建并发布 bundle,而无需有一个可用的正在运行的 CQ 实例。
尽管如此,在重部署环境下,只需简单激活这个 auto-deploy profile,然后每次在运行 Maven install 时 ,该 bundle 将会被自动重新部署到 CQ。命令行示例如下所示:
mvn -Pauto-deploy clean install
大多数常见的 IDE (Eclipse,NetBeans 等等) 都允许开发者在执行 Maven 构建的时候配置哪些 profile 是可用的。
通过 Maven properties 的使用将 Sling 的连接配置进行参数化也很重要,这样构建就可以轻松地在多个开发者的机器上执行,但在 POM 中还是要提供默认值。
<properties>
<crx.url>http://localhost:4502</crx.url>
<crx.user>admin</crx.user>
<crx.password>admin</crx.password>
</properties>
当默认值不可用的时候,可以使用标准 Maven 功能对它们进行轻松重写。对服务器 URL 进行命令行一次性构建重写的示例如下:
mvn -Pauto-deploy -Dcrx.url=http://localhost:8080 clean install
或者进行更永久化的重写,将该 property 直接添加到用户的 settings.xml 文件:
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
...
<profiles>
...
<profile>
<id>local-crx-settings</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<crx.url>http://localhost</crx.url>
</properties>
</profile>
</profiles>
</settings>
Maven 构建执行之后,如果部署成功,该 bundle 将会被安装并启动。取决于该 bundle 所做的事情,任何负面影响应该可以立即看到。最后,该 bundle 将会在管理员控制台的 Bundles 屏幕中列出,默认位置是:
http://localhost:4502/system/console/bundles
原文链接: Building & Deploying OSGi Bundles。
作者简介
CQBlueprints 网站旨在能够对使用 Adobe CQ 的架构师和开发人员提供一些帮助。尽管在 Adobe 的官方网站上已经有了很多关于 CQ 的相关信息,但是那些信息主要专注于 CQ 自身的产品。当你真正去落地 CQ 的时候你还得去考虑很多额外的课题(诸如,如何自主开发?开发的东西如何才能在部署环境下工作?)。 CQBlueprints 网站针对的正是这些问题。