Hi @aorlov
These will be included from 9.0.2 onwards
Hi @aorlov
These will be included from 9.0.2 onwards
Is this reproducible on 9.0.1?
Thanks for the detailed report @AndreasEbert
I’ve created CONFSERVER-97514 based on your report. Given that this is an edge case bug that is not specific to 9.0 and with a straightforward workaround available, it is of lower priority at this point in time.
Thanks @JnisVanags for your response. Can you please provide the maven dependency info where ‘com.atlassian.confluence.rest.v2.api.model’ package exists
I am getting compile issues,
package com.atlassian.confluence.rest.v2.api.model does not exist
In pom.xml I have
<dependency>
<groupId>com.atlassian.confluence</groupId>
<artifactId>confluence-rest-api</artifactId>
<version>8.5.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.atlassian.plugins.rest</groupId>
<artifactId>atlassian-rest-v2-api</artifactId>
<version>8.0.3</version>
<scope>provided</scope>
</dependency>
Thanks you!
@fgrund, yes, we still have classes that extend AbstractUserProfileAction
, although not directly but through other Confluence classes, namely ViewMyProfileAction
, ViewUserProfileAction
, and EditMyProfileAction
. But we don’t depend on FavouriteManager
, so it may not be applicable to your problem.
We ended up creating a copy of FavouriteManager
on our side.
Thanks! We’re getting the same error extending those classes as well though.
Maybe Atlassian can help with this? Maybe @mtran @mahesh @kmacleod ?
The problem: we have a small configuration page in the user profile section system.settings.edit/yoursettings
. This is implemented with an action that used to extend com.atlassian.confluence.user.actions.AbstractUserProfileAction
. On Confluence 9 we can’t install our app as soon as we extend this action:
Caused by: org.osgi.framework.BundleException: Unable to resolve XXX [292](R 292.0): missing requirement [XXX [292](R 292.0)] osgi.wiring.package; (&(osgi.wiring.package=com.atlassian.confluence.userstatus)(version>=9.0.1)(version<=9.0.1)) Unresolved requirements: [[XXX [292](R 292.0)] osgi.wiring.package; (&(osgi.wiring.package=com.atlassian.confluence.userstatus)(version>=9.0.1)(version<=9.0.1))]
at org.apache.felix.framework.Felix.resolveBundleRevision(Felix.java:4398)
at org.apache.felix.framework.Felix.startBundle(Felix.java:2308)
at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:1006)
at org.apache.felix.framework.BundleImpl.start(BundleImpl.java:992)
at com.atlassian.plugin.osgi.factory.OsgiPlugin.enableInternal(OsgiPlugin.java:408)
... 106 more
The problem is the package com.atlassian.confluence.userstatus
. The AbstractUserProfileAction
class has these imports which seem to cause the problem:
import com.atlassian.confluence.userstatus.FavouriteManager;
import com.atlassian.confluence.userstatus.StatusTextRenderer;
This also happens when we extend other subclasses of AbstractUserProfileAction
like ViewUserProfileAction
. We’re currently using a workaround that copies most of the code of AbstractUserProfileAction
and uses some reflection as well. We would really like to implement this properly. Any help would be appreciated!
@fgrund, I had this problem also when I was still using the <component>
-module style of dependency injection. I solved that by switching to Spring-Scanner (see my comment many months ago). So, just to double-check: You sure you’re correctly using either Spring-Scanner or Spring Java Config, and not the old-style <component>
-module style? You can check that by going to $baseUrl/plugins/servlet/upm/osgi, selecting your app and inspection the Import-Package-statements:
com.atlassian.confluence.userstatus
@fgrund If Andreas is correct, the root cause is not necessarily whether you are using Spring Scanner or Spring Java config vs <component>
, but whether or not the plugin is set up to be transformed upon load. The transformation is no longer needed when using Spring Scanner/Java config, but it might still be enabled inadvertently. This will be pointless (but harmless) on Confluence <=8, but transformation will generally always cause problems with Confluence 9+.
In this case, having a <Atlassian-Plugin-Key>
defined in the <Instructions>
for confluence-maven-plugin
in your pom is the key that prevents plugin transformation.
@scott.dudley @AndreasEbert Thank you so much for helping me out! We had in fact already migrated everything to Java config but hadn’t made this app transformerless yet (we’ve had lots of issues with the update, so I end up getting confused with all the different problems).
After I added Atlassian-Plugin-Key
I first ran into a Atlassian Cache crashes Confluence… first. After I applied the workaround with @Bean(destroyMethod="")
to cacheManager()
in my config file things started to work. Anyone knows if there has been any update to this? Seems we’re still supposed to use CacheManager rather than CacheFactory?
Anyway, I consider my problem solved, thanks again!!
@jens I was wondering whether you could make any progress with the WebPanel
incompatibility? We’re facing the same problem with the different packages.
Hi @fgrund,
I ended up using the velocity-based panel approach with an inline template and then simply created a context provider containing the logic instead of the custom WebPanel
implementation class. Fortunately the ContextProvider
interface has not been moved to a different package.
It works like this:
public class MetaTagsWebPanelContextProvider implements com.atlassian.plugin.web.ContextProvider {
...
public Map<String, Object> getContextMap(Map<String, Object> context) {
String html = ""; // Make sure to properly HTML-escape stuff
...
context.put("metaTagsHtml", html); // Map key must end with 'Html' to prevent velocity from HTML-escaping the output
return context;
}
}
And in atlassian-plugin.xml
:
<!-- Remove the 'class' attribute in the module element -->
<web-panel name="..." key="ui-context-panel" location="atl.header" weight="1100">
<!-- Set your ContextProvider class here -->
<context-provider class="com.k15t.scroll.exporter.infra.MetaTagsWebPanelContextProvider"/>
<!-- Use a velocity expression here to output the placeholder from the ContextProvider -->
<resource name="view" type="velocity">${metaTagsHtml}</resource>
<!-- ALTERNATIVELY, use a separate velocity template file -->
<resource name="view" type="velocity" location="templates/web-panel.vm"/>
</web-panel>
There might be a small performance benefit from using a standalone template file because Velocity should be able to cache the template object whereas for inline templates it always parses the template string on each request. I did not investigate this so far.
Hope this helps
@Kusal, @MichaelAndreacchio, coming back to <velocity-context-item>
not being auto-allowlisted: This effectively makes them unusable as public APIs
Background: We in our app want to offer such a velocity-context-item to other 3rd-party apps, see our docu for that. This is/should be possible, because velocity-context-item is globally available, not just to the own app.
Problem: Since they are not auto-allowlisted, 3rd-party apps would need to add their own allowlist-entries for class methods of such context-items. BUT, that is impossible because:
Plugins can only define allowlist entries for their own classes
I guess the more generic <template-context-item>
is also affected, even more obviously because it’s definitely meant to be available globally via attribute global="true"
, see docu.
Is this known to Atlassian and intentional? What can we do here?
Have you tested this scenario? That is allowlisting the methods of a <velocity-context-item>
or <template-context-item>
from your own plugin, then checking if they are invokable from another plugin?
@Kusal, yes, that works! Thanks for the quick help, much appreciated
So, I learned that velocity-allowlist entries are global and not scoped to the app. With that knowledge it makes sense that our app must allowlist its own velocity-context-items, even if it’s not using it itself. Cool, works for us
Could be helpful to add this to the docs, to make this more visible. I would not have made the connection on my own.
Glad to hear it worked - I suspected it would, but didn’t have time to double check myself. And yes that’s correct, even though additional allowlist entries are only accepted for classes which originate from that same plugin, the allowlist entries themselves are global.
I am trying to get the sample blueprint project “Bitbucket” running on Confluence 9.0.1, but it fails (after some version updates) during deployment with
[INFO] [talledLocalContainer] Caused by: org.osgi.framework.BundleException: Unable to resolve com.example.plugins.tutorial.confluence.simplebp [308](R 308.0): missing requirement [com.example.plugins.tutorial.confluence.simplebp [308](R 308.0)] osgi.wiring.package; (osgi.wiring.package=com.atlassian.confluence.plugins.createcontent.api.blueprint) Unresolved requirements: [[com.example.plugins.tutorial.confluence.simplebp [308](R 308.0)] osgi.wiring.package; (osgi.wiring.package=com.atlassian.confluence.plugins.createcontent.api.blueprint)]
and later
Package com.atlassian.confluence.plugins.createcontent.api.blueprint is internal and is not available for export to plugin com.example.plugins.tutorial.confluence.simplebp.simplebp
It is referenced from the docs at https://developer.atlassian.com/server/confluence/write-an-advanced-blueprint-plugin/ which seem to be updated just yesterday (Aug 6, 2024).
What am I missing?
Edit: This is the updated POM:
<modelVersion>4.0.0</modelVersion>
<groupId>com.example.plugins.tutorial.confluence.simplebp</groupId>
<artifactId>simplebp</artifactId>
<version>1.0-SNAPSHOT</version>
<organization>
<name>Example Company</name>
<url>http://www.example.com/</url>
</organization>
<name>simplebp</name>
<description>This is the com.example.plugins.tutorial.confluence.simplebp:simplebp plugin for Atlassian Confluence.</description>
<packaging>atlassian-plugin</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.atlassian.confluence</groupId>
<artifactId>confluence-plugins-platform-pom</artifactId>
<version>${confluence.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.atlassian.platform.dependencies</groupId>
<artifactId>platform-public-api</artifactId>
<version>${platform.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.atlassian.platform.dependencies</groupId>
<artifactId>platform-deprecated-public-api</artifactId>
<version>${platform.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.atlassian.confluence</groupId>
<artifactId>confluence</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.atlassian.plugin</groupId>
<artifactId>atlassian-spring-scanner-annotation</artifactId>
<version>${atlassian.spring.scanner.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.atlassian.confluence.plugins</groupId>
<artifactId>confluence-create-content-plugin</artifactId>
<version>${create.content.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.atlassian.plugin</groupId>
<artifactId>atlassian-spring-scanner-runtime</artifactId>
<version>${atlassian.spring.scanner.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.12.1</version>
<configuration>
<source>17</source>
<target>17</target>
<release>17</release>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>com.atlassian.maven.plugins</groupId>
<artifactId>confluence-maven-plugin</artifactId>
<version>${amps.version}</version>
<extensions>true</extensions>
<configuration>
<productVersion>${confluence.version}</productVersion>
<productDataVersion>${confluence.data.version}</productDataVersion>
<enableDevToolbox>false</enableDevToolbox>
<enablePde>false</enablePde>
<skipRestDocGeneration>false</skipRestDocGeneration>
<allowGoogleTracking>false</allowGoogleTracking>
<skipManifestValidation>true</skipManifestValidation>
<extractDependencies>false</extractDependencies>
<skipTests>true</skipTests>
<quickReloadVersion>5.0.8</quickReloadVersion>
<enableQuickReload>true</enableQuickReload>
<banningExcludes>
<exclude>com.atlassian.plugin:atlassian-spring-scanner-annotation</exclude>
<exclude>com.google.code.gson:gson</exclude>
</banningExcludes>
<!-- 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.example.plugins.tutorial.confluence.simplebp.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>
<scannedDependencies>
<dependency>
<groupId>com.atlassian.plugin</groupId>
<artifactId>atlassian-spring-scanner-external-jar</artifactId>
</dependency>
</scannedDependencies>
<verbose>false</verbose>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<confluence.version>9.0.1</confluence.version>
<confluence.data.version>9.0.1</confluence.data.version>
<platform.version>7.0.9</platform.version>
<create.content.version>19.0.50</create.content.version>
<amps.version>8.17.1</amps.version>
<atlassian.spring.scanner.version>5.0.2</atlassian.spring.scanner.version>
<!-- This key is used to keep the consistency between the key in atlassian-plugin.xml and the key to generate bundle. -->
<atlassian.plugin.key>${project.groupId}.${project.artifactId}</atlassian.plugin.key>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
Hi robert,
I got similar error sometimes, I would include the referred package in the “import-package” and the error will usually be resolved
For your case you can try to include
com.atlassian.confluence.plugins.createcontent.api.blueprint:resolution:=“optional”
Hi @KDanial,
Thank your for your helpful tip!
It took me some time since I did not get the Spring Scanner running with Confluence 9. Now I switched to Spring Java Config (I am more comfortable with) and the following allows to deploy the app:
<Import-Package>
org.springframework.osgi.*;resolution:="optional",
org.eclipse.gemini.blueprint.*;resolution:="optional",
com.atlassian.confluence.plugins.createcontent.api.*;resolution:="optional",
*
</Import-Package>
There was still an issue when I created a new page with this blueprint:
java.lang.RuntimeException occurred dispatching com.atlassian.confluence.plugins.createcontent.events.BlueprintPageCreateEvent to [com.example.plugins.tutorial.confluence.simplebp.MyBlueprintListener]
java.lang.ClassNotFoundException: com.atlassian.confluence.plugins.createcontent.api.blueprint.ContentBlueprint
With the (snipped) stack trace:
[INFO] [talledLocalContainer] 17:38:21,256 ERROR [http-nio-1990-exec-7 url: /confluence/rest/api/content/blueprint/instance/1081351; user: admin] [confluence.event.ConfluenceListenerInvoker] log java.lang.RuntimeException occurred dispatching com.atlassian.confluence.plugins.createcontent.events.BlueprintPageCreateEvent to [com.example.plugins.tutorial.confluence.simplebp.MyBlueprintListener]
[INFO] [talledLocalContainer] -- url: /confluence/rest/api/content/blueprint/instance/1081351 | userName: admin | referer: http://localhost:1990/confluence/pages/resumedraft.action?draftId=1081351&draftShareId=274211e6-921e-49f2-b8d0-bcbe355e244d& | traceId: b380fce617441f59
[INFO] [talledLocalContainer] java.lang.RuntimeException: com/atlassian/confluence/plugins/createcontent/api/blueprint/ContentBlueprint. Listener: com.example.plugins.tutorial.confluence.simplebp.MyBlueprintListener event: com.atlassian.confluence.plugins.createcontent.events.BlueprintPageCreateEvent
<snip>...</snip>
org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
[INFO] [talledLocalContainer] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63)
[INFO] [talledLocalContainer] at java.base/java.lang.Thread.run(Thread.java:840)
[INFO] [talledLocalContainer] Caused by: java.lang.NoClassDefFoundError: com/atlassian/confluence/plugins/createcontent/api/blueprint/ContentBlueprint
[INFO] [talledLocalContainer] at com.example.plugins.tutorial.confluence.simplebp.MyBlueprintListener.onBlueprintCreateEvent(MyBlueprintListener.java:28)
[INFO] [talledLocalContainer] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
[INFO] [talledLocalContainer] at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
[INFO] [talledLocalContainer] at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
[INFO] [talledLocalContainer] at java.base/java.lang.reflect.Method.invoke(Method.java:568)
[INFO] [talledLocalContainer] at com.atlassian.event.internal.SingleParameterMethodListenerInvoker.invoke(SingleParameterMethodListenerInvoker.java:42)
[INFO] [talledLocalContainer] ... 469 more
[INFO] [talledLocalContainer] Caused by: java.lang.ClassNotFoundException: com.atlassian.confluence.plugins.createcontent.api.blueprint.ContentBlueprint not found by com.example.plugins.tutorial.confluence.simplebp [309]
[INFO] [talledLocalContainer] at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1591)
[INFO] [talledLocalContainer] at org.apache.felix.framework.BundleWiringImpl.access$300(BundleWiringImpl.java:79)
[INFO] [talledLocalContainer] at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1976)
[INFO] [talledLocalContainer] at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525)
[INFO] [talledLocalContainer] ... 475 more
Then I added a compile scope dependency to the POM:
<dependency>
<groupId>com.atlassian.confluence.plugins</groupId>
<artifactId>confluence-create-content-api</artifactId>
</dependency>
And the “hello world blueprint project” works!
Thank you again!
Edit: Just in case someone would like to have a look at the code: https://bitbucket.org/smartics/confluence-eventlistener-blueprint/
Thanks a ton @jens ! We were able implement it like this as well !