将 Cloudinary 与 Adobe AEM 集成
Posted
技术标签:
【中文标题】将 Cloudinary 与 Adobe AEM 集成【英文标题】:Integrating Cloudinary with Adobe AEM 【发布时间】:2020-04-26 12:45:27 【问题描述】:我正在尝试将 Adobe AEM 6.3(在 Java 1.8 上运行)与 Cloudinary SDK 集成。我已经完成了以下操作,但是一直遇到我无法解决的异常。有没有人将 Cloudinary 与 AEM 集成并遇到类似问题?
-
在
pom.xml
中添加依赖,用于编译代码。
<dependency>
<groupId>com.cloudinary</groupId>
<artifactId>cloudinary-core</artifactId>
<version>1.24.0</version>
</dependency>
<dependency>
<groupId>com.cloudinary</groupId>
<artifactId>cloudinary-http44</artifactId>
<version>1.24.0</version>
</dependency>
构建 OSGI 插件以确保 AEM 获取正确的 jar 文件。为此,我按照create a third party RESTful service example 的步骤进行操作。要构建捆绑包,我必须明确下载以下 jar 文件:cloudinary-1.0.14.jar, cloudinary-core-1.21.0.jar, cloudinary-http44-1.21.0.jar, commons-codec-1.10.jar, commons-collections-3.2.2.jar, commons-lang3-3.1.jar, commons-logging-1.2.jar, httpclient-4.4.jar, httpmime-4.4.jar, jsp-api-2.0.jar
尽管创建了一个包含 httpclient
的包,但在尝试将图像上传到 Cloudinary 时出现以下异常。这是代码和异常。
代码 sn-p
import com.cloudinary.*;
..
Cloudinary cloudinary = new Cloudinary("<<credentials>>");
...
File toUpload = new File("/Users/akshayranganath/Downloads/background-2633962_1280.jpg");
try
Map uploadResult = cloudinary.uploader().upload(toUpload, ObjectUtils.emptyMap());
catch (IOException e)
// TODO Auto-generated catch block
e.printStackTrace();
异常
Caused by: java.lang.NoClassDefFoundError: javax/net/ssl/HostnameVerifier
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:756)
at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.defineClass(BundleWiringImpl.java:2370)
at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.findClass(BundleWiringImpl.java:2154)
at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1542)
at org.apache.felix.framework.BundleWiringImpl.access$400(BundleWiringImpl.java:79)
at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:2018)
at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
at org.apache.http.impl.conn.SchemeRegistryFactory.createDefault(SchemeRegistryFactory.java:52)
at org.apache.http.impl.client.AbstractHttpClient.createClientConnectionManager(AbstractHttpClient.java:321)
at org.apache.http.impl.client.AbstractHttpClient.getConnectionManager(AbstractHttpClient.java:484)
at org.apache.http.impl.client.AbstractHttpClient.createHttpContext(AbstractHttpClient.java:301)
at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:818)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:55)
at com.cloudinary.Uploader.callApi(Uploader.java:317)
at com.cloudinary.Uploader.upload(Uploader.java:57)
at com.aem.community.core.models.HelloWorldModel.init(HelloWorldModel.java:59)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.sling.models.impl.ModelAdapterFactory.invokePostConstruct(ModelAdapterFactory.java:792)
at org.apache.sling.models.impl.ModelAdapterFactory.createObject(ModelAdapterFactory.java:607)
... 211 common frames omitted
Caused by: java.lang.ClassNotFoundException: javax.net.ssl.HostnameVerifier not found by MyBundle [550]
at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1574)
at org.apache.felix.framework.BundleWiringImpl.access$400(BundleWiringImpl.java:79)
at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:2018)
at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
... 236 common frames omitted
这是我第一次使用 AEM,我可能没有遵循正确的步骤。请让我知道是否有人能够解决此问题。
更新
根据 Alexander 的建议和来自另一个来源的指针,我将以下代码添加到父 pom.xml
文件中。
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>3.5.0</version>
<configuration>
<instructions>
<Embed-Dependency>*;scope=compile|runtime</Embed-Dependency>
<Embed-Directory>OSGI-INF/lib</Embed-Directory>
<Embed-Transitive>true</Embed-Transitive>
</instructions>
</configuration>
</plugin>
进行此更改后,cloudinary 库被添加到包中。这是 AEM 的输出:http://localhost:4502/system/console/bundles
Embedded-Artifacts: OSGI-INF/lib/cloudinary-http44-1.21.0.jar; g="com.cloudinary"; a="cloudinary-http44"; v="1.21.0", OSGI-INF/lib/commons-lang3-3.1.jar; g="org.apache.commons"; a="commons-lang3"; v="3.1", OSGI-INF/lib/httpclient-4.4.jar; g="org.apache.httpcomponents"; a="httpclient"; v="4.4", OSGI-INF/lib/httpcore-4.4.jar; g="org.apache.httpcomponents"; a="httpcore"; v="4.4", OSGI-INF/lib/commons-logging-1.2.jar; g="commons-logging"; a="commons-logging"; v="1.2", OSGI-INF/lib/commons-codec-1.9.jar; g="commons-codec"; a="commons-codec"; v="1.9", OSGI-INF/lib/httpmime-4.4.jar; g="org.apache.httpcomponents"; a="httpmime"; v="4.4", OSGI-INF/lib/cloudinary-core-1.21.0.jar; g="com.cloudinary"; a="cloudinary-core"; v="1.21.0"
但是,我现在收到一条错误消息:
org.apache.avalon.framework.logger -- Cannot be resolved
org.apache.log -- Cannot be resolved
我可以通过添加依赖项Avalon framework 来解决org.apache.avalon.framework.logger
错误。但是,我无法克服org.apache.log
问题。似乎是版本冲突导致了问题。
当我包含Cloudinary http44 library 时,这个新错误就开始了。这个库似乎没有直接引用日志记录(有关依赖关系,请参阅here)。由于这个错误,应用程序仍然无法从 Installed 进入 Active 状态。
【问题讨论】:
Cloudinary 已经作为 OSGi 包提供。链接文档应该是您完全手动创建 OSGi 包的最后手段。查看maven-bundle-plugin
和Embed-Dependency
指令。这应该解决所有依赖项。但无论如何,这个问题是 OSGi 专家的问题 - 并且可能仍然是一项繁琐的任务。祝你好运。
谢谢你,亚历山大。在哪里可以找到 Cloudinary OSGi 捆绑包? Cloudinary SDK jar 文件似乎不是所需的 OSGI 格式。
对不起,这是我的错。我的意思是它是一个 Maven 神器。您可以将此类 jar 文件嵌入到您自己的包中,而无需将其作为全局 OSGi 包公开。您可以使用Embed-Dependency
来做到这一点。因此,您只需要 pom.xml 中的依赖项和嵌入指令 - 而不是下载 jar 文件并手动创建包。我明天尝试为您创建一个工作示例 pom.xml 作为答案。
谢谢你,亚历山大。我按照您的建议进行了更改并解决了问题的一部分。但是,现在似乎还有另一个错误,我已经用附加信息更新了原始问题。
对于记录器依赖问题,从 .m2 文件夹中删除两者,然后重试。
【参考方案1】:
Cloudinary-libs 可作为 Maven 工件使用。此类 JAR 文件可以作为私有库与 maven-bundle-plugin 一起放入您的包中。
以下示例适用于我(即使使用 Cloudinary 测试帐户)
...
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<executions>
<execution>
<!-- Create the bundle late in the compile-phase instead of the package-phase.
So the generated OSGi meta-data is available during JUnit tests. -->
<id>run-before-tests</id>
<phase>process-classes</phase>
<goals>
<goal>bundle</goal>
</goals>
</execution>
</executions>
<configuration>
<instructions>
<Bundle-Name>Test Bundle</Bundle-Name>
<Embed-Dependency>*;groupId=com.cloudinary;scope=compile|runtime</Embed-Dependency>
<Embed-Directory>OSGI-INF/lib</Embed-Directory> <!-- not needed, but nice -->
<Embed-Transitive>true</Embed-Transitive>
</instructions>
</configuration>
</plugin>
...
<dependencies>
<dependency>
<groupId>com.cloudinary</groupId>
<artifactId>cloudinary-core</artifactId>
<version>1.24.0</version>
</dependency>
<dependency>
<groupId>com.cloudinary</groupId>
<artifactId>cloudinary-http44</artifactId>
<version>1.24.0</version>
</dependency>
...
一般来说,嵌入一个外部库可以是简单、繁琐甚至是不可能的。这取决于导入的工件的依赖关系。
手动检查依赖树!(例如https://mvnrepository.com/)
你必须摆弄 3 条指令:
嵌入依赖
这是放在你的包中的库。小心使用星号运算符,否则您可能会包含太多依赖项(如果 AEM 很容易占据互联网的一半)。但不要包含的太少!提取构建的 bundle.jar,查看实际包含的内容(如果是 cloudinary,这很容易)。
导入包
通常这些库有太多的依赖关系,特别是如果库来自其他生态系统(如 Spring 或 JEE 容器),或者有很多半可选的依赖项。使用此设置,您可以告诉 OSGi,即使某些依赖项不可用,也可以激活捆绑包。
这是一个真实的例子:
<Import-Package>
!com.sun.msv.*,
!org.apache.log4j.jmx.*,
!sun.misc.*,
!org.jboss.logging.*,
!org.apache.zookeeper.*,
*
</Import-Package>
导出包
通常,库应该是捆绑私有的。但有时你必须以不同的方式导入,或者 lib 会自动执行某些操作。因此,您应该始终在系统控制台中检查您的捆绑包正在导出的内容。如果不正确,您必须手动修改此设置:
这是一个例子:
<Export-Package>
!*.internal,
!*.internal.*,
!*.impl,
!*.impl.*,
com.mycompany.myproject.mybundle.*
</Export-Package>
默认情况下,所有包*
都会被导出,除了它们被命名为impl
或internal
。他们的子包也是私有的(!*.impl.*
规则)。如果默认值不起作用,则使用此指令仅导出您需要的内容。
无论您导出什么,都会进入全球 OSGi 空间。此外,AEM 和 Sling-Bundle 并不完美,也不是 100% 没有错误,请确保
不应更改开箱即用 AEM 捆绑包的启动/关闭顺序 代码的部署、重新部署或取消部署不应启动/停止任何开箱即用的 AEM 捆绑包。如果您不确保这一点,您可能会遇到奇怪的部署问题 - 很难找到/解决。
因此,最好不要导出任何 AEM 开箱即用捆绑包导入的任何内容。其他一切仅供专家使用。甚至他们也高估了自己,低估了手动修补 AEM 的长期成本。
PS:_removeheaders
指令可以删除所有运行时不需要的 osgi 指令。但只有这样做,如果你想向公众提供一个捆绑包并让它完全闪亮。我会把它留在里面,因为它是某种文档。
【讨论】:
以上是关于将 Cloudinary 与 Adobe AEM 集成的主要内容,如果未能解决你的问题,请参考以下文章
以编程方式读取 Adobe 游戏变量/与游戏/游戏机器人交互
如何导出与 Flash Player 8 兼容的 Adobe Flash cc 文件?
在 Adobe 和浏览器都将结束 Adobe Flash 之后,有啥方法可以运行 Web 应用程序