Как остановить maven-shade-plugin от блокировки java.util.ServiceLoader инициализация типов opensaml-impl
При использовании OpenSAML 3 сначала необходимо загрузить компоненты из opensaml-saml-impl
Артефакт со следующей строкой кода:
InitializationService.initialize();
Это использует java.util.ServiceLoader
загрузить любой тип, который реализует Initializer
,
Когда я пишу тест и запускаю его с mvn integration-test
, это работает нормально, и я вижу, что все загрузилось:
Assert.assertTrue(
XMLObjectProviderRegistrySupport
.getUnmarshallerFactory()
.getUnmarshallers()
.size() > 400);
Тем не менее, мой проект использует maven-shade-plugin
, Вышеуказанное условие неверно, если я упаковываю код в uber-jar:
mvn package
java -jar /path/to/my.jar
В этом случае я наблюдаю, что загружено только 9 unmarshallers opensaml-core
в отличие от тех, кто в opensaml-saml-impl
, Тем не менее, когда я смотрю на выходе mvn package
Я вижу, что типы включены в затененную банку:
[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.
Я могу обойти эту проблему с помощью следующего кода:
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();
}
Это полностью разрушает смысл системы плагинов, но позволяет моей программе функционировать.
Для справки вот соответствующие биты 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://stackru.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>
1 ответ
Когда вы используете плагин Maven Shade с зависимостями, используя ServiceLoader
API, вы должны использовать ServicesResourceTransformer
, который предназначен для объединения файлов. Если плагин перемещает классы, он также будет правильно перемещать имена классов в каждом сервисном файле, в отличие от AppendingTransformer
,
Так что вы можете просто заменить свой текущий AppendingTransformer
с
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
Это будет гарантировать, что каждый файл службы под META-INF/services
из ваших зависимостей объединяются, без необходимости объявлять их все.