Как остановить 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 из ваших зависимостей объединяются, без необходимости объявлять их все.

Другие вопросы по тегам