问题描述
使用OpenSAML 3时,必须首先使用以下代码行从opensaml-saml-impl
项目中加载组件:
When using OpenSAML 3, you must first load components from the opensaml-saml-impl
artifact with the following line of code:
InitializationService.initialize();
此使用java.util.ServiceLoader
加载实现了 .
当我编写测试并使用mvn integration-test
运行它时,它工作正常,并且可以看到所有内容都已加载:
When I write a test and run it with mvn integration-test
, this works fine, and I can see that everything has loaded:
Assert.assertTrue(
XMLObjectProviderRegistrySupport
.getUnmarshallerFactory()
.getUnmarshallers()
.size() > 400);
但是,我的项目使用的是maven-shade-plugin
.如果我将代码打包到uber-jar中,则上述条件为 not true:
However, my project uses maven-shade-plugin
. The condition above is not true if I package the code into an uber-jar:
mvn package
java -jar /path/to/my.jar
在这种情况下,我观察到仅加载了9个解组器(opensaml-core
中的解组器,与opensaml-saml-impl
中的解组器相反.但是,当我观察mvn package
的输出时,我可以看到类型包括在阴影罐中:
In this case I observe that only 9 unmarshallers have loaded (those in opensaml-core
, as opposed to those in opensaml-saml-impl
. However, when I watch the output of mvn package
, I can see that the types are included in the shaded jar:
[INFO] Including org.opensaml:opensaml-saml-impl:jar:3.2.0 in the shaded jar.
[INFO] Including org.opensaml:opensaml-profile-api:jar:3.2.0 in the shaded jar.
[INFO] Including org.opensaml:opensaml-messaging-api:jar:3.2.0 in the shaded jar.
[INFO] Including org.opensaml:opensaml-saml-api:jar:3.2.0 in the shaded jar.
[INFO] Including org.opensaml:opensaml-xmlsec-api:jar:3.2.0 in the shaded jar.
[INFO] Including org.opensaml:opensaml-soap-api:jar:3.2.0 in the shaded jar.
[INFO] Including org.opensaml:opensaml-storage-api:jar:3.2.0 in the shaded jar.
[INFO] Including org.opensaml:opensaml-security-impl:jar:3.2.0 in the shaded jar.
[INFO] Including org.opensaml:opensaml-security-api:jar:3.2.0 in the shaded jar.
我可以使用以下哑代码解决此问题:
I can work around this issue with the following dumb code:
private static void initManuallyInsteadOfWithInitializationServiceSoThatMavenShadePluginDoesNotRemoveThem() throws InitializationException {
new ApacheXMLSecurityInitializer().init();
new ClientTLSValidationConfiguratonInitializer().init();
new GlobalAlgorithmRegistryInitializer().init();
new GlobalParserPoolInitializer().init();
new GlobalSecurityConfigurationInitializer().init();
new JavaCryptoValidationInitializer().init();
new SAMLConfigurationInitializer().init();
new org.opensaml.core.xml.config.XMLObjectProviderInitializer().init();
new org.opensaml.xmlsec.config.XMLObjectProviderInitializer().init();
new XMLObjectProviderInitializer().init();
}
这完全打败了插件系统,但确实允许我的程序运行.
This utterly defeats the point of the plugin system, but it does allow my program to function.
作为参考,这是pom.xml
的相关位:
For reference, here's the relevant bits of pom.xml
:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Main-Class>com.example.Server</Main-Class>
</manifestEntries>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/services/io.vertx.core.spi.VerticleFactory</resource>
</transformer>
</transformers>
<artifactSet>
</artifactSet>
<outputFile>${project.build.directory}/${project.artifactId}-${project.version}-fat.jar
</outputFile>
<filters>
<filter>
<!-- Fix java.lang.SecurityException: Invalid signature file digest for Manifest main attributes
when server starts inside Docker container due to inclusion of OpenSAML and use of
uber-jar / maven-shade-plugin. See http://stackoverflow.com/a/6743609 -->
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
<filter>
<!-- This was one of my attempts to fix the problem.
Unfortunately, it doesn't work. -->
<artifact>org.opensaml:opensaml-saml-impl</artifact>
<includes>
<include>**</include>
</includes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
推荐答案
使用带有ServiceLoader
API的依赖关系的Maven Shade插件时,应使用 ServicesResourceTransformer
专用于将文件合并在一起.如果插件是重定位类,它将还可以在中正确地重新定位每个服务文件中的类名.
When you're using the Maven Shade Plugin with dependencies using the ServiceLoader
API, you should use the ServicesResourceTransformer
, which is dedicated to merge together the files. If the plugin is relocating classes, it will also relocate properly the class names in each service file, unlike the AppendingTransformer
.
因此,您只需将当前的AppendingTransformer
替换为
So you can just replace your current AppendingTransformer
with
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
这将确保合并依赖项中META-INF/services
下的每个服务文件,而无需全部声明它们.
It will make sure that every service file under META-INF/services
of your dependencies are merged, without the need to declare them all.
这篇关于如何阻止Maven-shade-plugin阻止opensaml-impl类型的java.util.ServiceLoader初始化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!