JPMS/Jigsaw keycloak-spring-boot-starter (invalid module name & ResolutionException)

Viewed 263

the Java 11 maven application is modularized with JPMS/Jigsaw.

Problem 1: keycloak-spring-boot-2-adapter invalid module-name '2'

Solution 1: Renamed by maven plugin with removed "-2". But I'm not sure if this is a good solution.

<plugin>
   <!-- for copying dependent libraries to folder lib -->
   <groupId>org.apache.maven.plugins</groupId>
   <artifactId>maven-dependency-plugin</artifactId>
   <executions>
      <execution>
         <id>copy-dependencies</id>
         <phase>package</phase>
         <goals>
            <goal>copy-dependencies</goal>
         </goals>
         <configuration>
            <outputDirectory>../lib</outputDirectory>
            <excludeGroupIds>com.xyz</excludeGroupIds>
            <excludeArtifactIds>keycloak-spring-boot-2-adapter</excludeArtifactIds>
         </configuration>
      </execution>
      <execution>
         <id>copy</id>
         <phase>package</phase>
         <goals>
            <goal>copy</goal>
         </goals>
         <configuration>
            <artifactItems>
               <artifacItem>
                  <groupId>org.keycloak</groupId>
                  <artifactId>keycloak-spring-boot-2-adapter</artifactId>
                  <overWrite>true</overWrite>
                  <outputDirectory>../lib</outputDirectory>
                  <destFileName>keycloak-spring-boot-adapter-9.0.2.jar</destFileName>
               </artifacItem>
            </artifactItems>
            <!-- other configurations here -->
         </configuration>
      </execution>
   </executions>
</plugin>

Problem 2: keycloak.spring.boot.adapter and keycloak.spring.boot.adapter.core have the same package name.

java.lang.module.ResolutionException: Modules keycloak.spring.boot.adapter and keycloak.spring.boot.adapter.core export package org.keycloak.adapters.springboot to module org.yaml.snakeyaml

Solution 2: ?

Thanks for your help and best regards,

Pierre

2 Answers

There is a ticket (KEYCLOAK-12499) with two sub tasks describing the two problems you're facing: KEYCLOAK-9072 (Problem 1) and KEYCLOAK-9073 (Problem 2).

The first problem is a trivial one, both from your perspective as from the perspective of the maintainers of Keycloak.

The second problem however requires more work because two (actually three) artifacts are sharing the same package and are exporting it when they are used as automatic modules (because automatic modules export all of their packages).
Exporting the same package from more than one module is not allowed however (http://openjdk.java.net/projects/jigsaw/spec/reqs/#non-interference).
The three artifacts involved in this problem are keycloak-spring-boot-adapter-core, keycloak-spring-boot-adapter and keycloak-spring-boot-2-adapter. The adapter-core artifact works somewhat like an abstract implementation for the two other modules and provides package private classes and methods which are used by the other two modules.
The emphasized text is the core of the second problem: sharing a package across different artifacts works for classic Java without modules, but the module system blocks this because it breaks encapsulation.
Solving the second problem requires you to make copies of keycloak-spring-boot-adapter-core and keycloak-spring-boot-2-adapter and adjust their code — at least until there is a fix for the official artifacts.

A solution for problem 2 is building an own automatic module.

Create a new module and add a POM with the following build plugins and dependency.

<dependency>
    <groupId>org.keycloak</groupId>
    <artifactId>keycloak-spring-boot-2-adapter</artifactId>
    <version>9.0.2</version>
    <exclusions>
        <exclusion>
        <groupId> org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        </exclusion>
        ...
    </exclusions>
</dependency>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-clean-plugin</artifactId>
        </plugin>
        <!-- Maven Assembly Plugin -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>3.1.1</version>
            <configuration>
                <!-- get all project dependencies -->
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
                <appendAssemblyId>false</appendAssemblyId>
                <outputDirectory>../mods</outputDirectory>
                <archive>
                    <manifestEntries>
                        <Automatic-Module-Name>modulename</Automatic-Module-Name>
                    </manifestEntries>
                </archive>
            </configuration>
            <executions>
                <execution>
                    <id>make-assembly</id> <!-- this is used for inheritance merges -->
                    <phase>package</phase> <!-- bind to the packaging phase -->
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-install-plugin</artifactId>
            <version>2.5.2</version>
            <executions>
                <execution>
                    <id>install-external</id>
                    <phase>install</phase>
                    <configuration>
                        <file>${project.basedir}/../mods/modulename-1.0-SNAPSHOT.jar</file>
                        <repositoryLayout>default</repositoryLayout>
                        <groupId>com.xyz.assembly</groupId>
                        <artifactId>modulename</artifactId>
                        <version>1.0-SNAPSHOT</version>
                        <packaging>jar</packaging>
                        <generatePom>true</generatePom>
                    </configuration>
                    <goals>
                        <goal>install-file</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

You can add the dependency via com.xyz.assembly as groupID to other modules.

But keep attention! It will use the module-info.java of log4j if you don't exclude it in this assembly module.

Related