Confluence 10.0 release EAP is available now

Dear @clouless

did you try specifying a banningExcludes section inside the configuration section of the confluence-maven-plugin? I for example use:

            <plugin>
                <groupId>com.atlassian.maven.plugins</groupId>
                <artifactId>confluence-maven-plugin</artifactId>
                <version>${amps.version}</version>
                <extensions>true</extensions>
                <configuration>
                    ...
                    
                    <banningExcludes>
                    	<exclude>org.json:json</exclude>
                    </banningExcludes>
                </configuration>
            </plugin>

Best regards

Andreas

1 Like

Try adding this :

                    <banningExcludes>
                        <exclude>org.apache.commons:commons-text</exclude>
                        <exclude>commons-codec:commons-codec</exclude>
                        <exclude>com.google.code.gson:gson</exclude>
                    </banningExcludes>
1 Like

@Kusal, starting with 10.0.0-m28 we cannot resolve com.atlassian.confluence.user.persistence.dao.ConfluenceUserDao anymore. We use its getAll() for clean-up purposes because it also returns deleted users (i.e. userAccessor.exists(user.getName()) == false). Is there another way to access it? Or another way for getting all users, incl. deactivated and deleted ones?

Hi!

I test 10.0.0-m28 use com.plugin.atlassian.plugins.rest:atlassian-rest-v2-plugin:9.0.0-jakarta-m008 (from confluence-plugins-platform-pom:10.0.0-m28), java 21 and have this error

Caused by: java.lang.IllegalArgumentException: Unsupported class file major version 66
	at org.objectweb.asm.ClassReader.<init>(ClassReader.java:199)
	at org.objectweb.asm.ClassReader.<init>(ClassReader.java:180)
	at org.objectweb.asm.ClassReader.<init>(ClassReader.java:166)
	at org.objectweb.asm.ClassReader.<init>(ClassReader.java:287)
	at com.atlassian.plugins.rest.v2.scanner.JarIndexer.getClassReader(JarIndexer.java:99)
	... 112 more

Stacktrace shows this class com.atlassian.plugins.rest.v2.scanner.JarIndexerException. But java version 66 is java 22. Right? Did I get something wrong or this artifact was compiled for java 22?

Kind regards

Full Stacktrace
com.atlassian.plugins.rest.v2.scanner.JarIndexerException: Error accessing input stream of the jar file /var/atlassian/application-data/confluence/plugins-cache/1743502456117my-plugin-6.0.1-SNAPSHOT.jar
	at com.atlassian.plugins.rest.v2.scanner.JarIndexer.getClassReader(JarIndexer.java:101)
	at com.atlassian.plugins.rest.v2.scanner.JarIndexer.analyzeClassFile(JarIndexer.java:83)
	at com.atlassian.plugins.rest.v2.scanner.JarIndexer.scanJar(JarIndexer.java:71)
	at com.atlassian.plugins.rest.v2.scanner.AnnotatedClassScanner.scan(AnnotatedClassScanner.java:46)
	at com.atlassian.plugins.rest.v2.jersey.ResourceConfigFactory.createConfig(ResourceConfigFactory.java:99)
	at com.atlassian.plugins.rest.v2.servlet.RestDelegatingServletFilter.<init>(RestDelegatingServletFilter.java:69)
	at com.atlassian.plugins.rest.v2.descriptor.RestServletFilterModuleDescriptor.<init>(RestServletFilterModuleDescriptor.java:42)
	at com.atlassian.plugins.rest.v2.descriptor.RestModuleDescriptor.enabled(RestModuleDescriptor.java:171)
	at com.atlassian.plugin.manager.DefaultPluginManager.lambda$notifyModuleEnabled$47(DefaultPluginManager.java:1994)
	at com.atlassian.plugin.manager.PluginTransactionContext.wrap(PluginTransactionContext.java:64)
	at com.atlassian.plugin.manager.DefaultPluginManager.notifyModuleEnabled(DefaultPluginManager.java:1990)
	at com.atlassian.plugin.manager.DefaultPluginManager.lambda$enableConfiguredPluginModule$32(DefaultPluginManager.java:1718)
	at com.atlassian.plugin.manager.PluginTransactionContext.wrap(PluginTransactionContext.java:73)
	at com.atlassian.plugin.manager.DefaultPluginManager.enableConfiguredPluginModule(DefaultPluginManager.java:1700)
	at com.atlassian.plugin.manager.DefaultPluginManager.lambda$enableConfiguredPluginModules$31(DefaultPluginManager.java:1688)
	at com.atlassian.plugin.manager.PluginTransactionContext.wrap(PluginTransactionContext.java:73)
	at com.atlassian.plugin.manager.DefaultPluginManager.enableConfiguredPluginModules(DefaultPluginManager.java:1685)
	at com.atlassian.plugin.manager.DefaultPluginManager.lambda$enableDependentPlugins$24(DefaultPluginManager.java:1314)
	at com.atlassian.plugin.manager.PluginTransactionContext.wrap(PluginTransactionContext.java:64)
	at com.atlassian.plugin.manager.DefaultPluginManager.enableDependentPlugins(DefaultPluginManager.java:1280)
	at com.atlassian.plugin.manager.DefaultPluginManager.lambda$addPlugins$22(DefaultPluginManager.java:1264)
	at com.atlassian.plugin.manager.PluginTransactionContext.wrap(PluginTransactionContext.java:64)
	at com.atlassian.plugin.manager.DefaultPluginManager.addPlugins(DefaultPluginManager.java:1151)
	at com.atlassian.plugin.manager.DefaultPluginManager.lambda$scanForNewPlugins$14(DefaultPluginManager.java:953)
	at com.atlassian.plugin.manager.PluginTransactionContext.wrap(PluginTransactionContext.java:64)
	at com.atlassian.plugin.manager.DefaultPluginManager.scanForNewPlugins(DefaultPluginManager.java:907)
	at com.atlassian.plugin.manager.DefaultPluginManager.lambda$installPlugins$13(DefaultPluginManager.java:866)
	at com.atlassian.plugin.manager.PluginTransactionContext.wrap(PluginTransactionContext.java:64)
	at com.atlassian.plugin.manager.DefaultPluginManager.installPlugins(DefaultPluginManager.java:853)
	at com.atlassian.confluence.impl.plugin.EventDispatchingPluginController.installPlugins(EventDispatchingPluginController.java:74)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source)
	at java.base/java.lang.reflect.Method.invoke(Unknown Source)
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:359)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:380)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:223)
	at jdk.proxy4/jdk.proxy4.$Proxy471.installPlugins(Unknown Source)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source)
	at java.base/java.lang.reflect.Method.invoke(Unknown Source)
	at com.atlassian.plugin.util.ContextClassLoaderSettingInvocationHandler.invoke(ContextClassLoaderSettingInvocationHandler.java:26)
	at jdk.proxy4/jdk.proxy4.$Proxy837.installPlugins(Unknown Source)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source)
	at java.base/java.lang.reflect.Method.invoke(Unknown Source)
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:359)
	at org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceInvoker.doInvoke(ServiceInvoker.java:56)
	at org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceInvoker.invoke(ServiceInvoker.java:60)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
	at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:137)
	at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
	at org.eclipse.gemini.blueprint.service.util.internal.aop.ServiceTCCLInterceptor.invokeUnprivileged(ServiceTCCLInterceptor.java:70)
	at org.eclipse.gemini.blueprint.service.util.internal.aop.ServiceTCCLInterceptor.invoke(ServiceTCCLInterceptor.java:53)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
	at org.eclipse.gemini.blueprint.service.importer.support.LocalBundleContextAdvice.invoke(LocalBundleContextAdvice.java:57)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
	at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:137)
	at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:223)
	at jdk.proxy24/jdk.proxy24.$Proxy1031.installPlugins(Unknown Source)
	at com.atlassian.upm.core.install.AbstractPluginInstallHandler$1.doInTransaction(AbstractPluginInstallHandler.java:115)
	at com.atlassian.upm.core.install.AbstractPluginInstallHandler$1.doInTransaction(AbstractPluginInstallHandler.java:112)
	at com.atlassian.sal.core.transaction.HostContextTransactionTemplate$1.doInTransaction(HostContextTransactionTemplate.java:21)
	at com.atlassian.sal.spring.component.SpringHostContextAccessor.lambda$doInTransaction$0(SpringHostContextAccessor.java:72)
	at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140)
	at com.atlassian.sal.spring.component.SpringHostContextAccessor.doInTransaction(SpringHostContextAccessor.java:70)
	at com.atlassian.sal.core.transaction.HostContextTransactionTemplate.execute(HostContextTransactionTemplate.java:18)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source)
	at java.base/java.lang.reflect.Method.invoke(Unknown Source)
	at com.atlassian.plugin.util.ContextClassLoaderSettingInvocationHandler.invoke(ContextClassLoaderSettingInvocationHandler.java:26)
	at jdk.proxy4/jdk.proxy4.$Proxy525.execute(Unknown Source)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source)
	at java.base/java.lang.reflect.Method.invoke(Unknown Source)
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:359)
	at org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceInvoker.doInvoke(ServiceInvoker.java:56)
	at org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceInvoker.invoke(ServiceInvoker.java:60)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
	at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:137)
	at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
	at org.eclipse.gemini.blueprint.service.util.internal.aop.ServiceTCCLInterceptor.invokeUnprivileged(ServiceTCCLInterceptor.java:70)
	at org.eclipse.gemini.blueprint.service.util.internal.aop.ServiceTCCLInterceptor.invoke(ServiceTCCLInterceptor.java:53)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
	at org.eclipse.gemini.blueprint.service.importer.support.LocalBundleContextAdvice.invoke(LocalBundleContextAdvice.java:57)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
	at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:137)
	at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:223)
	at jdk.proxy24/jdk.proxy24.$Proxy929.execute(Unknown Source)
	at com.atlassian.upm.core.install.AbstractPluginInstallHandler.installArtifacts(AbstractPluginInstallHandler.java:112)
	at com.atlassian.upm.core.install.ObrPluginInstallHandler.installResources(ObrPluginInstallHandler.java:225)
	at com.atlassian.upm.core.install.ObrPluginInstallHandler.installPluginInternal(ObrPluginInstallHandler.java:151)
	at com.atlassian.upm.core.install.AbstractPluginInstallHandler.installPlugin(AbstractPluginInstallHandler.java:55)
	at com.atlassian.upm.core.install.DefaultPluginInstallationService.execute(DefaultPluginInstallationService.java:173)
	at com.atlassian.upm.core.install.DefaultPluginInstallationService.install(DefaultPluginInstallationService.java:113)
	at com.atlassian.upm.install.UpmPluginInstallationService.install(UpmPluginInstallationService.java:129)
	at com.atlassian.upm.core.rest.resources.install.InstallTask.installFromFile(InstallTask.java:132)
	at com.atlassian.upm.core.rest.resources.install.InstallFromFileUploadTask.lambda$executeTask$0(InstallFromFileUploadTask.java:83)
	at com.atlassian.upm.api.util.Either$Right.fold(Either.java:138)
	at com.atlassian.upm.core.rest.resources.install.InstallFromFileUploadTask.executeTask(InstallFromFileUploadTask.java:81)
	at com.atlassian.upm.core.rest.resources.install.InstallTask.run(InstallTask.java:80)
	at com.atlassian.upm.core.async.AsynchronousTaskManager.executeTask(AsynchronousTaskManager.java:117)
	at com.atlassian.upm.core.async.AsynchronousTaskManager$1.call(AsynchronousTaskManager.java:99)
	at com.atlassian.upm.core.async.AsynchronousTaskManager$1.call(AsynchronousTaskManager.java:97)
	at com.atlassian.sal.core.executor.ThreadLocalDelegateCallable.call(ThreadLocalDelegateCallable.java:38)
	at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
	at java.base/java.lang.Thread.run(Unknown Source)
Caused by: java.lang.IllegalArgumentException: Unsupported class file major version 66
	at org.objectweb.asm.ClassReader.<init>(ClassReader.java:199)
	at org.objectweb.asm.ClassReader.<init>(ClassReader.java:180)
	at org.objectweb.asm.ClassReader.<init>(ClassReader.java:166)
	at org.objectweb.asm.ClassReader.<init>(ClassReader.java:287)
	at com.atlassian.plugins.rest.v2.scanner.JarIndexer.getClassReader(JarIndexer.java:99)
	... 112 more

Hi,

May I ask if you guys have a roadmap on releases for the 10.0?

I am asking that mostly to get an idea on how long do we have to make our plugin compatible while being retro compatible.

I do understand that’s just an estimate but that would greatly help to get an idea of the minimum time we have.

Thank you.

Bruno means, do you have a date? I mean, it will take at least 2 months before the release, won’t it? We’re just trying to organize our priorities locally.

It’s a sensible suggestion and one which we intend to action at some point, although it may not be in 10.0.

I believe your question has been answered above. Unfortunately the AMPS plugin enforcer rule is not DMZ aware so you should add necessary exclusions to work around it.

Are either of the following APIs suitable for your use case?

  • com.atlassian.confluence.user.ConfluenceUserResolver#getUsersByUserKeys(List<UserKey>)
  • com.atlassian.confluence.user.ConfluenceUserResolver#getUsers(LimitedRequest)

The stacktrace seems to be suggesting the opposite - that it is your plugin which was compiled with Java 22.

We do not. Very roughly, the beta will probably be in July.

2 Likes

@Kusal No, unfortunately not because they don’t return deleted users (the JavaDoc of getUsers() also mentions this).
But I did find an alternative after all by looking into how Confluence’s /admin/users/showallunsyncedusers.action does it: Using com.atlassian.confluence.api.service.people.PersonService.PersonSearcher#forUnsyncedUsers like so:

List<Person> deletedUsers = personService.search()
        .forUnsyncedUsers("")
        .fetchMany(new SimplePageRequest(0, 100))
        .getResults();
// in the end, I need UserKeys of deleted users in order to clean-up my app's data
List<String> deletedUserKeys = deletedUsers.stream()
        .map(p -> p.optionalUserKey().map(UserKey::getStringValue).orElse(null))
        .toList();

I successfully tested this with Confluence 9.3 and 10.0.0-m28, so far so good.

Can you confirm that PersonService.PersonSearcher is public API and not being planned for removal soon? Wouldn’t wan to rework this code again soon…

Hi @Kusal

Is it possible to look into fixing the XsrfTokenGenerator somehow so that it can be used without requiring compile-time visibility of the old javax.servlet package?

Presumably due to the new “default” methods added to the interface, I cannot compile the following client code against the 10.0.0-m28 milestone. I receive the following error on compilation, even though I do not reference the javax.servlet classes at all:

BadClass.java:21:27
java: cannot access javax.servlet.http.HttpServletRequest
  class file for javax.servlet.http.HttpServletRequest not found

Code:

package mypackage;

import com.atlassian.struts.xsrf.XsrfTokenGenerator;
import jakarta.inject.Inject;
import org.springframework.stereotype.Component;

@Component
public class BadClass
{
    private XsrfTokenGenerator xsrfTokenGenerator;

    @Inject
    public BadClass(XsrfTokenGenerator xsrfTokenGenerator)
    {
        this.xsrfTokenGenerator = xsrfTokenGenerator;
    }

    public void test()
    {
        jakarta.servlet.http.HttpServletRequest req = null;
        xsrfTokenGenerator.generateToken(req);
    }
}

The only way I can get this code to compile is to include the old javax.servlet-api in the pom with compile scope, but I fear that this will eventually stop working when this gets banned (and I would rather not have it on the compile classpath to prevent inadvertent errors).

The above code is just an example where req could be inferred to be null by the compiler, but the problem also occurs in production code where the HttpServletRequest is a valid jakarta servlet object.

Thanks!

Additionally, the XsrfTokenGenerator bean is apparently no longer exported. Is there a replacement?

ERROR [ThreadPoolAsyncTaskExecutor::Thread 28] [extender.internal.support.ExtenderConfiguration] onOsgiApplicationEvent Application context refresh failed (NonValidatingOsgiBundleXmlApplicationContext(bundle=mybundle config=osgibundle:/META-INF/spring/*.xml))
 -- url: /confluence/rest/plugins/1.0/ | userName: admin | referer: http://confluence:8090/confluence/plugins/servlet/upm | traceId: 7506c08530766bd5
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'MyBean': Unsatisfied dependency expressed through constructor parameter 8: No qualifying bean of type 'com.atlassian.struts.xsrf.XsrfTokenGenerator' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@com.atlassian.plugin.spring.scanner.annotation.imports.ComponentImport("")}

Excellent

Yes, the APIs in com.atlassian.confluence.api are part of our official Java API and are at significantly lower risk of breaking changes.

This is a known issue (with this and some other classes) and will be fixed soon. Having javax.servlet-api in provided scope should be sufficient as a workaround for now.

It should still be exported - there may be a different configuration issue with your plugin. Do also ensure you’re using Atlassian Spring Scanner 6.0.0.

1 Like

Hi @Kusal

The plugin is built with Spring Scanner v6.0.0-jakarta-m001, and I also confirmed that the output Spring MANIFEST.MF has an Import-Package for com.atlassian.struts.xsrf. The same app is correctly importing dozens of other beans (so this is the only one that fails).

I first noticed this problem within the -m28 milestone, whereas it was previously working in at least some earlier 10.0 milestones.

Any other ideas? Although anything is possible, I do not believe I changed anything in this regard.

I am having trouble getting Apache Commons Fileupload to work.
Can someone please outline what do to, thanks:

Which of the four possibilities is the right one?

  1. commons-fileupload2-jakarta-serverl5 to use Jakarta Servlets 5.
  2. commons-fileupload2-jakarta-serverl6 to use Jakarta Servlets 6.
  3. commons-fileupload2-javax to use Javax Servlets.
  4. commons-fileupload2-portlet to use Javax Portlets.

I am very lost :face_in_clouds: thanks

For my REST Endpoints I now get this error on app startup:

Package javax.ws.rs is internal and is not available for export to plugin

EDIT: This only applies to Struts/XWork actions.
We use com.atlassian.confluence.struts.StrutsHelper#getUploadedFile in our app. We read about it in Preparing for Confluence 10.0 → Struts 7.0 upgrade. Sample code for a Struts action class:

import com.atlassian.struts.multipart.FileUploadException;
import com.atlassian.struts.multipart.UploadedFile;
...

UploadedFile uploadedFile = null;
try {
    // strutsHelper is provided by ConfluenceActionSupport
    uploadedFile = strutsHelper.getUploadedFile(getActiveRequest(), "my-file-id");
    try (Reader fileReader = new FileReader(uploadedFile.getFile())) {
        ...
    }
} catch (IOException | FileUploadException e) {
    ...
} finally {
    if (uploadedFile != null) {
        MyFileUtils.deleteTempFile(uploadedFile.getFile());
    }
}
2 Likes

Hi,

We have an issue with our rest resources after switching to Jakarta. In our pom, we switched from Javax to the respective Jakarta packages in the provided scope and used the recommended DependencyManagement confluence-plugins-platform-pom. So we did not have to specify any Jakarta versions. Then we replaced all javax with jakarta imports, besides javax.ws.rs. It seems like the provided jakarta.ws.rs version 2.1.6 still exports everything as javax.ws.rs, is this correct?

The plugin enables successfully, but none of our resources seem to work, I only get 404s. Any ideas what could be the reason for this?

1 Like

@Kusal Well, lessons learnt:

  • Testing in Struts actions is not the same as in a scheduled job.
  • And PersonService checks permissions of the currently logged-in user – in scheduled jobs there is no logged-in user:
2025-04-04 16:38:17,029 ERROR [Caesium-1-4] [impl.schedule.caesium.JobRunnerWrapper] runJob Scheduled job de.communardo.confluence.plugins.userprofile:purgeUserDataJob#purgeUserDataJobKey-runNow-1743777496958 failed to run
com.atlassian.confluence.api.service.exceptions.PermissionException: User not permitted to view user profiles
	at com.atlassian.confluence.api.model.validation.SimpleValidationResult.lambda$static$0(SimpleValidationResult.java:30)
	at com.atlassian.confluence.api.model.validation.SimpleValidationResult.convertToServiceException(SimpleValidationResult.java:81)
	at com.atlassian.confluence.api.model.validation.ValidationResult.throwIfNotSuccessful(ValidationResult.java:195)
	at com.atlassian.confluence.api.impl.service.people.PersonServiceImpl.search(PersonServiceImpl.java:297)
    ...

So, I don’t think PersonService is a viable alternative for us after all :confused:
Thinking of solutions, I know we can set the logged-in user (via AuthenticatedUserThreadLocal#set), but we wouldn’t know which admin-user to pick. Sure, we could make that configurable to the customer, but that feels clunky.
We’d like to have ConfluenceUserDao back – or another way to fetch deleted users in a scheduled job without user-context.

Any suggestions would be much appreciated.

1 Like

For whatever reason, the XsrfTokenGenerator bean can no longer be autowired (or at least not from the context of a <velocity-context-item>, and perhaps not elsewhere).

Despite this, I discovered that it can still be retrieved manually in the constructor like this:

this.xsrfTokenGenerator = ContainerManager.getComponent("xsrfTokenGenerator", XsrfTokenGenerator.class)

Handling multipart uploads is recommended to be done in the following ways:

  • For REST APIs: Using the annotations in package com.atlassian.plugins.rest.api.multipart
  • For Struts Actions: Using the com.atlassian.confluence.struts.StrutsHelper OSGi service
  • For custom Servlets: Using the utilities in org.apache.commons.fileupload2.jakarta.servlet6

You should double check your POM configuration as the confluence-plugins-platform-pom is not providing that old version for jakarta.ws.rs-api. You should not have any javax.ws.rs imports in your plugin.

I’ll have to get back to you on this. It may be possible we need to introduce a new API.

I’ll have to test this myself and get back to you as I can’t at first glance see any recent changes that should prevent it.

That API uses a completely different mechanism. It retrieves a Spring bean by-name from the internal Confluence Spring context. It’s not officially supported.

The usual injection methods (<component-import> [transformed], @ComponentImport [Spring Scanner] and #importOsgiService [Spring Java config]) retrieves public OSGi services by type.

2 Likes

Thanks @Kusal I found an example app for the Multipart Upload REST API.

But for some reason I get these errors now:

2025-04-07 06:43:54,517 ERROR [UpmAsynchronousTaskManager:thread-1] [atlassian.plugin.manager.PluginEnabler] actualEnable Unable to enable plugin codeclou-app-confluence-common
com.atlassian.plugin.osgi.container.OsgiContainerException: Cannot start plugin: codeclou-app-confluence-common
Caused by: org.osgi.framework.BundleException: Unable to resolve io.codeclou.app-confluence-common [288](R 288.0): 
  missing requirement [io.codeclou.app-confluence-common [288](R 288.0)] osgi.wiring.package; (osgi.wiring.package=com.atlassian.plugins.osgi.javaconfig) 
  Unresolved requirements: [[io.codeclou.app-confluence-common [288](R 288.0)] osgi.wiring.package; (osgi.wiring.package=com.atlassian.plugins.osgi.javaconfig)]

The app worked fine in Confluence 9 with the javaconfig. I have not changed anything on that part. Is there any new config I need? thanks

        <confluence.version>10.0.0-m28</confluence.version>
        <confluence.data.version>10.0.0-m28</confluence.data.version>
        <platform.version>7.0.13</platform.version>
        <amps.version>9.2.5</amps.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>21</maven.compiler.source>
        <maven.compiler.target>21</maven.compiler.target>

The atlassian-plugins-osgi-javaconfig artifact should be bundled with your plugin rather than imported (i.e. compile scope).

1 Like