Unresolved requirements for Java packages I don't use while migrating home-grown Confluence plugin to work with 9.2.0

Hi folks,

I am migrating a simple, home-grown Confluence plugin containing a couple macros to work with 9.2.0 per these instructions.

The only third party package I import is “org.apache.commons.validator.routines.UrlValidator”.

So, I added this line to my pom.xml:

<dependency>
    <groupId>commons-validator</groupId>
    <artifactId>commons-validator</artifactId>
    <version>1.5.1</version>
</dependency>

Compiled, then uploaded it to a sandbox Confluence data center 9.2.0 environment I have, and it spit out this error:

2025-01-22 15:56:24,113 ERROR [UpmAsynchronousTaskManager:thread-1] [atlassian.plugin.manager.PluginEnabler] actualEnable Unable to enable plugin com.redacted.testMacros

Caused by: org.osgi.framework.BundleException: Unable to resolve com.redacted.testMacros [293](R 293.0): missing requirement [com.redacted.testMacros [293](R 293.0)] osgi.wiring.package; (osgi.wiring.package=org.apache.avalon.framework.logger) Unresolved requirements: [[com.redacted.testMacros [293](R 293.0)] osgi.wiring.package; (osgi.wiring.package=org.apache.avalon.framework.logger)]

I don’t want to repeat myself too much here, but although I was unfamiliar with thatorg.apache.avalon.framework.logger package, I looked it up on maven repository and added it as a dependency as well. Compiled, uploaded again, and now I get an error message saying I was missing a requirement for org.apache.log, then repeat the process and next time I am missing a requirement for com.conversantmedia.util.concurrent. At this point I decided to stop because clearly something else is wrong. I have no idea why it suddenly thinks it needs these packages, I’m not using them anywhere.

Here is a full list of all the imports I use throughout all my Java code for this plugin:

import com.atlassian.confluence.content.render.xhtml.ConversionContext;
import com.atlassian.confluence.macro.Macro;
import com.atlassian.confluence.macro.MacroExecutionException;
import com.atlassian.confluence.renderer.radeox.macros.MacroUtils;
import com.atlassian.confluence.util.velocity.VelocityUtils;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
import com.atlassian.renderer.RenderContext;
import com.atlassian.renderer.v2.RenderMode;
import com.atlassian.renderer.v2.macro.BaseMacro;
import com.atlassian.renderer.v2.macro.MacroException;
import org.apache.commons.validator.routines.UrlValidator;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.UUID;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Collections;

And here is my pom.xml file:

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion>
    <groupId>com.redacted.testMacros</groupId>
    <artifactId>testMacros</artifactId>
    <version>1.0.0-SNAPSHOT</version>

    <organization>
        <name>Example Company</name>
        <url>http://www.example.com/</url>
    </organization>

    <name>Redacted</name>
    <description>Redacted.</description>
    <packaging>atlassian-plugin</packaging>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.10</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.atlassian.confluence</groupId>
            <artifactId>confluence</artifactId>
            <version>${confluence.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>com.atlassian.plugin</groupId>
            <artifactId>atlassian-spring-scanner-annotation</artifactId>
            <version>${atlassian.spring.scanner.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
            <scope>provided</scope>
        </dependency>

        <!-- WIRED TEST RUNNER DEPENDENCIES -->
        <dependency>
            <groupId>com.atlassian.plugins</groupId>
            <artifactId>atlassian-plugins-osgi-testrunner</artifactId>
            <version>${plugin.testrunner.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>javax.ws.rs</groupId>
            <artifactId>jsr311-api</artifactId>
            <version>1.1.1</version>
            <scope>provided</scope>
        </dependency>

        <!-- CUSTOM ADDED DEPENDENCIES -->
        <dependency>
            <groupId>commons-validator</groupId>
            <artifactId>commons-validator</artifactId>
            <version>1.5.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.avalon.framework/avalon-framework-api -->
        <dependency>
            <groupId>org.apache.avalon.framework</groupId>
            <artifactId>avalon-framework-api</artifactId>
            <version>4.3.1</version>
            <scope>compile</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.23.1</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>com.atlassian.maven.plugins</groupId>
                <artifactId>confluence-maven-plugin</artifactId>
                <version>${amps.version}</version>
                <extensions>true</extensions>
                <configuration>
                    <!-- LM ADDED, exclude banning of dependencies -->
                    <banningExcludes>
                        <exclude>commons-validator:commons-validator</exclude>
                        <exclude>commons-collections:commons-collections</exclude>
                    </banningExcludes>
                    <productVersion>${confluence.version}</productVersion>
                    <productDataVersion>${confluence.data.version}</productDataVersion>
                    <enableQuickReload>true</enableQuickReload>

                    <systemPropertyVariables>
                        <atlassian.dev.mode>false</atlassian.dev.mode>
                        <upm.plugin.upload.enabled>true</upm.plugin.upload.enabled>
                    </systemPropertyVariables>


                    <!-- See here for an explanation of default instructions: -->
                    <!-- https://developer.atlassian.com/docs/advanced-topics/configuration-of-instructions-in-atlassian-plugins -->
                    <instructions>
                        <Atlassian-Plugin-Key>${atlassian.plugin.key}</Atlassian-Plugin-Key>

                        <!-- Add package to export here -->
                        <Export-Package>
                            com.lmco.cbamacros.api,
                        </Export-Package>

                        <!-- Add package import here -->
                        <Import-Package>
                            org.springframework.osgi.*;resolution:="optional",
                            org.eclipse.gemini.blueprint.*;resolution:="optional",
                            *
                        </Import-Package>

                        <!-- Ensure plugin is spring powered -->
                        <Spring-Context>*</Spring-Context>
                    </instructions>

                </configuration>
            </plugin>
            <plugin>
                <groupId>com.atlassian.plugin</groupId>
                <artifactId>atlassian-spring-scanner-maven-plugin</artifactId>
                <version>${atlassian.spring.scanner.version}</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>atlassian-spring-scanner</goal>
                        </goals>
                        <phase>process-classes</phase>
                    </execution>
                </executions>
                <configuration>
                    <verbose>false</verbose>
                </configuration>
            </plugin>
        </plugins>
    </build>

    <properties>
        <confluence.version>9.2.0</confluence.version>
        <confluence.data.version>9.2.0</confluence.data.version>
        <amps.version>9.1.1</amps.version>
        <plugin.testrunner.version>2.0.9</plugin.testrunner.version>
        <atlassian.spring.scanner.version>2.2.4</atlassian.spring.scanner.version>
        <!-- This property ensures consistency between the key in atlassian-plugin.xml and the OSGi bundle's key. -->
        <atlassian.plugin.key>${project.groupId}.${project.artifactId}</atlassian.plugin.key>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

</project>

Any help would be appreciated. This plugin worked perfectly fine through LTS 8.5 and I wasn’t expecting it to completely break for the next LTS.

Have you tried adding in the <scope> on this? It mentions on that page you referenced that you should be using <scope>runtime</scope> or <scope>compile</scope>

If you tried to add in the <scope>, what happened?

Thanks for the suggestion, but unfortunately neither of those work. Also, if you don’t specify a scope, it uses compile by default.

Solved!

Turns out, including a package as a dependency doesn’t actually make it export with the final .jar far after packaging the project.

I followed these StackOverflow instructions and ultimately added this section to my pom.xml:

  <build>
    <plugins>
      <!-- any other plugins -->
      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
        </configuration>
      </plugin>
    </plugins>
  </build>

Then, in the target output folder, it also makes a file called {projectName}-{projectVersion}-jar-with-dependencies.jar, and uploaded that file through the UPM (universal plugin manager) solves the problem.