Preparing for Confluence 8.0 - EAP coming soon

…although how would we even migrate the data to AO, given that we can’t read large amounts of Bandana data in a performant manner in the first place, at least not without also having to completely reinvent the wheel while bypassing Bandana as mentioned above? :thinking:

I am struggling with finding the names of modules to use with AMD instead of the global variables we are currently using.

I managed that our app runs using AMD on Confluence 7.4.x. Now I try to run this version on Confluence 8.0 (m12) and I get errors like

  • tinymce missing confluence-editor/init
  • TypeError: Cannot read properties of undefined (reading ‘create’)
  • Cannot read properties of undefined (reading ‘registerInitHandler’)

The last one is due my use of AJS.Confluence.PropertyPanel.Macro.registerButtonHandler I originally found in the (now legacy) tutorial Extending the macro property panel. What would be the proper replacement?

I can see definitions and requirements in the code like

define('confluence-quick-edit/handlers/comment/edit', [
    'confluence/root',
    'confluence/templates',
    'wrm/context-path',
    'confluence/dark-features',
    'confluence/api/logger',
    'confluence/meta',
    'confluence-editor/profiles',
    'confluence-quick-edit/handlers/comment',
    'confluence-quick-edit/quick-edit',
    'jquery',
], function(
    Confluence,
    ConfluenceTemplates,
    contextPath,
    DarkFeatures,
    logger,
    Meta,
    Profiles,
    QuickComment,
    QuickEdit,
    $
...

but I cannot tell whether ‘Confluence’ for ‘confluence/root’ is actually the replacement for the global variable with the same name or is it ‘confluence/legacy’ which I found in another example. How can I find out what is inside a module and the name of the web resource that defines it?

Should confluence/meta replace the AJS.Meta references or could I still use AJS (via the ‘ajs’) to access this information?

And finally what is the difference between confluence.web.resources:ajs and com.atlassian.auiplugin:ajs?

Is there information on the Web that explains some of my questions above? Is there a list of web resources / module names to help to replace global variables?

It would be very helpful, at least to me, if you could add some pointers to some resources on Preparing for Confluence 8.0.

Hi @scott.dudley,

There’re significant benefits to moving to AO, as you observe.

Bandana is using Spring’s HibernateTemplate which looks for an open Session bound to the thread. In the case it doesn’t find a Session, one is created and configured with flushMode(MANUAL). Unfortunately this isn’t ever going to occur as Confluence initiates a new Session at the start of each HTTP request. This Session is configured with flushMode(AUTO) by default, which will exhibit the behaviour you’re working around. This isn’t something that can be fixed without a significant reworking of underlying Confluence systems.

As you observed, PluginHibernateSessionFactory is being replaced by EntityManagerProvider, and it doesn’t support flushMode(NEVER). It does, however, support flushMode(COMMIT) which could work for your purposes assuming you’re able to load all of the records in a single transaction.

Alternately, you could attempt to obtain a read-only transaction using Spring’s PlatformTransactionManager. This is exposed to plugins, and can be configured with readOnly=true and propagation=requiresNew in the Spring TransactionDefinition. This should combine to produce an EntityManager with the same behaviour as flushMode(MANUAL).

Hopefully this provides a path forward.

Thanks,
James Ponting
Engineering Manager - Confluence Data Center

Hi @rr1,
I’ll answer some of your questions below:

I believe registerButtonHandler is still a valid method to use.
confluence/root is AMD module for AJS.Confluence btw

‘confluence/root’ and ‘confluence/legacy’ are the same object.
You can find out what is inside a module by these steps:

  1. Open browser dev tool
  2. Require a module and assign it to a variable, e.g
x=require('confluence/root')
y=require('confluence/legacy')
  1. Then inspect those objects to see what is inside them , or do a comparison x===y

It may be tricky to find out name of the web resource that defines it (sometimes this method may not work).

  1. Open dev tool on Chrome
  2. Click on Search tab (or press shortcut on Mac : Cmd + Opt + F)
  3. Fill in module name, e.g confluence/legacy
  4. From the search result, look for line that contains the name standing close to beginning of line, that is the line where module name is defined, something like define('confluence/legacy' or define("confluence/legacy".
  5. Click on that line. It will bring you to source code. The module is often wrapped inside a try/catch block. You can see a commented code showing web resource name, e.g /* module-key = 'confluence.web.resources:amd', location = '/includes/js/amd/shim/confluence-mobile-amd.js' */

Please see screenshot for example:

Yes, you should use AMD confluence/meta. You should avoid global variable as much as possible.

com.atlassian.auiplugin:ajs is resource provided by cross product plugin AUI : https://aui.atlassian.com/
confluence.web.resources:ajs this resource is included by Confluence to override something from AUI and also load some additional resources that are not included in com.atlassian.auiplugin:ajs

Currently I don’t have info on this thing, I’ll do some search to see if those documentation is available

Without a more detail on how you implement your app (dependency order, AMD usage …), I can’t point out exactly what the problem is. My best guess is you may not declare dependency on editor core resource in atlassian-plugin.xml file. The web resource name for editor is com.atlassian.confluence.plugins:confluence-editor-plugin which contains AMD module confluence-editor/init

Hi @NamHo,

Thank you very much for your explanations! They help me a lot! Also as a confirmation that this is the intended way to program with the JS API. :slight_smile: It makes this difference between assuming and knowing (like the difference between the lightning bug and the lightning) and it feels a lot better now.

Meanwhile I was searching a couple of hours in the browser’s downloaded JS code and in the Confluence sources (the confluence-editor/init was actually not defined) and was able to find a handful of dependency candidates I desperately added and it fixed the problem. I will now check if I can replace all my findings with com.atlassian.confluence.plugins:confluence-editor-plugin. But I am unsure if I should do it since your recommendation is to use confluence/meta instead of confluence.web.resources:ajs to access AJS.Meta.

define('com/mycorp/mymodule',
  ['ajs', 'tinymce'],
  function (AJS, tinymce) {
    "use strict";
...
    AJS.Meta.get('base-url') ...

I’ll figure that out …

Thank you again for your great support! It feels like I am out of the swamp and back on track.

Hi @rr1 ,
Web resource (confluence.web.resources:ajs) and AMD module (confluence/meta) are 2 different aspects.
Web resource is a collection of JS, CSS and something else. Those JS can be AMD or none-AMD.
I recommend using confluence/meta as a replacement for AJS.Meta. confluence/meta module is included in web resource confluence.web.resources:ajs.
So you must specify a dependency on confluence.web.resources:ajs in atlassian-plugin.xml file in order to use module confluence/meta in javascript

Hi @NamHo,

Thank you for your clarification. I am not sure if my understanding of AMD and global variables is correct.

I thought that I can use the module ajs because of the dependency confluence.web.resources:ajs by the name of the variable AJS and that AJS.Meta can be accessed via that variable.

I assume that part of your response is referring to my wrong reference “confluence/meta instead of confluence.web.resources:ajs” (web resource) where I should have written " confluence/meta instead of ajs (module)? I now understand that both modules are part of the same web resource.

So should I use the following code fragment instead of what I have written in my last post (assuming that I still need AJS for e.g. AJS.$(...) somewhere in my code) or would the reference AJS.Meta be okay?

define('com/mycorp/mymodule',
  ['ajs', 'tinymce', 'confluence/meta'],
  function (AJS, tinymce, Meta) {
    "use strict";
...
    Meta.get('base-url') ...

I thought that AJS.Meta (since AJS ist defined in the function) is actually using the ajs module and not the global variable. I assume that this is wrong?

Hi @rr1 ,
Your latest code is correct

define('com/mycorp/mymodule',
  ['ajs', 'tinymce', 'confluence/meta'],
  function (AJS, tinymce, Meta) {
    "use strict";
...
    Meta.get('base-url') ...

In the future, Meta will no longer be attached to the AJS object, so AJS.Meta will be undefined.

Hi @NamHo,
Thank you again! My code now works and I have couple of pointers and a better understanding to further take advantage of AMD.

1 Like

8.0.0-m018 has been published 5 days ago, but the EAP page doesn’t have a changelog for this milestone.
Any chance this could be added so we know what’s in?

Is there some (rough) timeframe for the platform updates and/or lucene API isolation?

Thanks!

1 Like

Hi Jens, added now. So sorry for the delay to confirm changes with our team: Preparing for Confluence 8.0 | Confluence Data Center and Server 7.18 | Atlassian Documentation

In terms of an ETA for Lucene API isolation, I’ve passed your question to our engineers and will come back to you shortly.

2 Likes

Hi,
I work on the ScriptRunner for Confluence team and we are looking for help with the Log4j 2.x upgrade.

We currently use many exported packages from Log4j for our logging implementations, which power some of our core features. Some of these packages (e.g. org.apache.log4j.spi) will no longer be exported in Confluence 8, breaking our usage our ability to dynamically create log appenders. For example, the ability for customers to use debugging statements in their scripts will break:

There is no equivalent way that we can see to provide the same functionality using SLF4J, since it doesn’t control appenders. Can you elaborate on decision to remove access to the Log4j 2.x API for
plugins?

Thanks!

2 Likes

Hey @jens,

The Lucene API isolation will be in Confluence 8.0 as a feature, and we expect to have the actual work completed into an EAP towards the start of September. As with all such things, this is subject to change depending on all the normal things.

We have a task to work through documentation all the search V2 unification work in the next sprint, so we should have that out soon as well.

Hopefully this help :slight_smile:

Thanks,
James Ponting
Engineering Manager - Confluence Data Center

Thanks @jponting!

Some of our apps define lucene-query-mapper modules. Am I understanding the announcements correctly, that this will no longer be possible (because the mapper implementations create lucene objects)?
Here’s the query mapper module’s interface for reference:

package com.atlassian.confluence.search.v2.lucene;

import com.atlassian.confluence.search.v2.SearchQuery;
import org.apache.lucene.search.Query;

public interface LuceneQueryMapper<T extends SearchQuery> {
    Query convertToLuceneQuery(T searchQuery);
}

Seems this is deprecated in Confluence 7.5 sources, but not in 7.18 anymore. :face_with_raised_eyebrow:

We’re also defining custom lucene-search-filter-mapper and lucene-boosting-strategy modules.

Will there be any replacement APIs for 3rd party apps? This would result in a major refactoring of our apps and most probably a loss of features otherwise.

Cheers,
Jens

1 Like