Using conditions from bitbucket-web-common

Hi, according to https://developer.atlassian.com/bitbucket/server/docs/latest/reference/plugin-module-types/client-web-panel.html it’s possible to add <condition> tag to <client-web-panel>.

    <client-web-panel name="Changed new repository instructions" key="new-git-repo-refresh" location="bitbucket.empty.repository.instructions" weight="1">
        <description>Adds recommendation to refresh the new repository page</description>
        <resource name="view" type="soy" location="org.xxx.xxx.bitbucket.epo-bitbucket-plugin:client-side-resources/org.xxx.xxx.bitbucket.main" />
        <condition class="com.atlassian.bitbucket.web.conditions.IsPersonalRepositoryCondition" invert="true" />
    </client-web-panel>

Condition classes are in bitbucket-web-common.jar, which, according to https://developer.atlassian.com/bitbucket/server/docs/latest/reference/java-api.html, can be added to add-on by

        <dependency>
            <!-- includes conditions for displaying panels -->
            <groupId>com.atlassian.bitbucket.server</groupId>
            <artifactId>bitbucket-web-common</artifactId>
            <scope>provided</scope>
        </dependency>

So we did. However now add-on fails to start with ClassNotFoundException: com.atlassian.bitbucket.web.conditions.IsPersonalRepositoryCondition not found by org.epo.cbs.bitbucket.epo-bitbucket-plugin [127]. Attempts to add the dependency on bitbucket-web-common in compile scope result in OSGI problems.

Any recommendations?

Thank you,
Viktor

Had to resolve this by writing my own implementation of IsPersonalRepositoryCondition ;-(

The provided scope should work, but you’ll need to include the package in the <Import-Package> section in your pom.xml. Something like this should work:

    <build>
        <plugins>
            <plugin>
                <groupId>com.atlassian.maven.plugins</groupId>
                <artifactId>bitbucket-maven-plugin</artifactId>
                <extensions>true</extensions>
                <configuration>
                    <extractDependencies>true</extractDependencies>
                    <instructions>
                        <Atlassian-Plugin-Key>${project.groupId}.${project.artifactId}</Atlassian-Plugin-Key>
                        <Export-Package>
                           <!-- exports here, if any -->
                        </Export-Package>
                        <Import-Package>
                            com.atlassian.bitbucket.web.conditions,
                            com.atlassian.bitbucket*,
                            <!-- further imports here -->
                            *
                        </Import-Package>
                        <Spring-Context>*</Spring-Context>
                    </instructions>
                </configuration>
            </plugin>

Thank you! Will give it a try next time I run into a similar problem

Due to upgrade to support 5.X version of BitBucket, time to try solution from @mheemskerk has come. BitBucket version in pom.xml changed to 5.3.1, version of Spring Scanner moved to 2.1.3.

Attempt to use IsPersonalRepositoryCondition from bitbucket-web-common:

[INFO] Caused by: com.atlassian.plugin.web.conditions.ConditionLoadingException: Cannot load condition class: com.atlassian.bitbucket.web.conditions.IsPersonalRepositoryCondition
[INFO]  at com.atlassian.stash.internal.plugin.StashConditionFactory.create(StashConditionFactory.java:36)
[INFO]  at com.atlassian.stash.internal.plugin.OsgiSafeProxyProvider$1.invoke(OsgiSafeProxyProvider.java:93)
[INFO]  at com.atlassian.plugin.web.descriptors.ConditionElementParser.makeConditionImplementation(ConditionElementParser.java:86)
[INFO]  ... 32 common frames omitted
[INFO] Caused by: java.lang.ClassNotFoundException: com.atlassian.bitbucket.web.conditions.IsPersonalRepositoryCondition not found by org.epo.cbs.bitbucket.epo-bitbucket-plugin [129]
[INFO]  at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1532)
[INFO]  at com.atlassian.stash.internal.plugin.StashConditionFactory.create(StashConditionFactory.java:29)
[INFO]  ... 34 common frames omitted

This happens in spite of importing the packages in bitbucket-maven-plugin:6.3.3 and the class being available in bitbucket-web-common:5.3.1

<Import-Package>
    org.springframework.osgi.*;resolution:="optional",
    org.eclipse.gemini.blueprint.*;resolution:="optional",
    com.atlassian.plugin.web.*,
    com.atlassian.plugin.web.baseconditions.*,
    com.atlassian.bitbucket.web.conditions.*
    *
</Import-Package>

This warning appears when manifest is being generated [WARNING] Manifest org.xxx.bitbucket:xxx-bitbucket-plugin:atlassian-plugin:1.0.11-SNAPSHOT : Unused Import-Package instructions: [org.springframework.osgi.*, org.eclipse.gemini.blueprint.*, com.atlassian.plugin.web.*, com.atlassian.bitbucket.web.conditions.*, com.atlassian.plugin.web.baseconditions.*]

Attempt to use our own implementation of the condition

[INFO] org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [org.epo.cbs.bitbucket.repo.IsPersonalRepositoryCondition]; nested exception is java.io.FileNotFoundException: OSGi resource[classpath:com/atlassian/plugin/web/baseconditions/BaseCondition.class|bnd.id=129|bnd.sym=org.epo.cbs.bitbucket.epo-bitbucket-plugin] cannot be resolved to URL because it does not exist
[INFO]  at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:181)
[INFO]  at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:308)
....
....
[INFO]  at org.eclipse.gemini.blueprint.extender.internal.activator.LifecycleManager$1.run(LifecycleManager.java:207)
[INFO]  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
[INFO]  at java.lang.Thread.run(Thread.java:748)
[INFO]  ... 1 frame trimmed
[INFO] Caused by: java.io.FileNotFoundException: OSGi resource[classpath:com/atlassian/plugin/web/baseconditions/BaseCondition.class|bnd.id=129|bnd.sym=org.epo.cbs.bitbucket.epo-bitbucket-plugin] cannot be resolved to URL because it does not exist
[INFO]  at org.eclipse.gemini.blueprint.io.OsgiBundleResource.getURL(OsgiBundleResource.java:229)
[INFO]  at org.eclipse.gemini.blueprint.io.OsgiBundleResource.getInputStream(OsgiBundleResource.java:181)
[INFO]  at org.springframework.core.type.classreading.SimpleMetadataReader.<init>(SimpleMetadataReader.java:50)

Interesting is that public class IsPersonalRepositoryCondition implements Condition. Condition interface is defined in atlassian-plugins-webfragment-api:4.1.0 and it extends BaseCondition from the same library. Condition is found, but BaseCondition is not

Seems I found the cause of the problem and solution.

The cause: when using com.atlassian.bitbucket.web.conditions.IsPersonalRepositoryCondition, the plugin misses com.atlassian.bitbucket.auth.AuthenticationContext in META-INF/plugin-components/imports file. AuthenticationContext is used by the condition class, but its implementation is not found at runtime. When I copied code of IsPersonalRepositoryCondition into the plugin project and annotated it for Spring scanner, AuthenticationContext got annotated with @ComponentImport and therefore Maven plugin added the missing line to imports file.

Solution: adding <component-import> to atlassian-plugin.xml is rejected by Maven plugin. Therefore I added ComponentsImporter class to the project. This class annotates the required components with @ComponentImport and let the generated plugin to include them in imports file. See example

1 Like