Release Notes for XWiki 12.4

Last modified by Simon Urli on 2021/02/05

This is the release notes for XWiki Commons, XWiki Rendering and XWiki Platform. They share the same release notes as they are released together and have the same version.

This version brings some usability improvements such as simpler to use Include and Display macros, a new experimental and more performant notification store, and a lot of developer-level improvements (the work continued for the new User API, easier to implement inline editing of forms, API to modify configuration sources, a Mail obfuscation API, and more).

New and Noteworthy (since XWiki 12.3)

Full list of issues fixed and Dashboard for 12.4.

For Users

Selection preserved when switching between WYSIWYG and Source

 
We upgraded the CKEditor Integration extension and the new version comes with a long-awaited feature: the selection / caret is preserved when switching between WYSIWYG and Source area. This makes it really easy to:

  • check the wiki syntax that corresponds to the current WYSIWYG selection
  • check how the selected text from the Source area is rendered when switching back to WYSIWYG

Exclude Heading in Include/Display Macros

 
It's now possible to exclude the heading from an included page for both Include and Display macros, if the first element of that page is a heading.

Miscellaneous

  • Simplify usage of Include macro: It's now simpler to use the Include and Display macros. Some complex and never-used parameters have been removed from the WYISWYG editor's macro dialog UI. Specifically, the page parameter is now hidden and for the Include macro the context parameter is now deprecated (and thus hidden). This also allows to display a single way to choose the reference of the included/displayed page and to ensure that users use the provided page picker.

  • Object editor does not save automatically on object creation/deletion anymore: The behaviour of the Object editor changed to be more consistent: the changes performed like object addition or deletion are now only saved when clicking on the save button.

    Note that for developers we introduced new saving parameters to allow adding and deleting objects on a single save.

For Admins

  • New experimental event store: A new Solr based event store has been introduced. It's still disabled by default (will be enabled as soon as the user notification use case is fully refactored to use it) and meant to be used more and more to replace the current Hibernate based event and event status store.

For Developers

Extension Manager improvements

 

  • Extension without any associated file are now supported (Extension#getType() return null or empty string in this case)
  • Maven modules of type pom or dependencies of type pom produce Extension with empty type
  • In general Extension Manager now have a better support for Maven dependencies of type different from the default type (this produce extensions with different ids on Extension Manager side)

User Properties

 
There's now an API to modify user properties. Scripting example:

{{velocity}}
#set ($props = $services.user.getProperties("testuser"))
#set ($discard = $props.setEmail('[email protected]'))
#set ($discard = $props.setFirstName('John'))
#set ($discard = $props.save())
{{/velocity}}

Default object sheet supports in-place editing

 
If you create a new application on top of XWiki following the manual FAQ tutorial you'll notice that starting with this version the application entries are editable in-place, from view mode. You can achieve the same thing for an existing application by copying and adjusting the code of the XWiki.ObjectSheet page over your existing sheet. Just make sure you update the name of the class used in the copied code.

Miscellaneous

  • Mail Address HTML Displayer: An HTML Displayer for email addresses (i.e. objects of type javax.mail.internet.InternetAddress) has been added (it displays the email address obfuscated if obfuscation is on). It's not used anywhere but can be called. Scripting example:

    {{velocity}}
    #set ($email = $services.user.properties.email)
    {{html}}
    $services.display.html.display('javax.mail.internet.InternetAddress', $email)
    {{/html}}
    {{/velocity}}
  • Mail Address Conversion: There's now a Converter to convert from a String to an InternetAddress and vice versa. It's especially important since we've modified the User API's get/setEmail() to use an InternetAddress. This allows using Velocity scripts that call APIs accepting an InternetAddress by passing a string. For example:

    $services.user.properties.setEmail("[email protected]")
  • Ability to hide macro parameters in WYSIWYG: Thanks to the introduction of a new @ProperyDisplayHidden annotation that can be placed on Macro parameter classes, it's now possible to hide the parameter inside the WYSIWYG's Macro editor. This is useful to hide complex parameters that should only be used in wiki edit mode for example.

    Example:

    public class IncludeMacroParameters
    {
    ...
       /**
         * @param type the type of the reference
         * @since 3.4M1
         */

        @PropertyDescription("the type of the reference")
        @PropertyGroup("stringReference")
        @PropertyAdvanced
       // Marking it as Display Hidden because it's complex and we don't want to confuse our users.
        @PropertyDisplayHidden
       public void setType(EntityType type)
        {
           this.type = type;
        }

       /**
         * @param page the reference of the page to include
         * @since 10.6RC1
         */

        @PropertyDescription("The reference of the page to include")
        @PropertyDisplayType(PageReference.class)
        @PropertyFeature("reference")
       // Display hidden because we don't want to confuse our users by proposing two ways to enter the reference to
       // include and ATM we don't have a picker for PageReference types and we do have a picker for EntityReference string
       // one so we choose to keep the other one visible and hide this one. We're keeping the property so that we don't
       // break backward compatibility when using the macro in wiki edit mode.
        @PropertyDisplayHidden
       public void setPage(String page)
        {
           this.reference = page;
           this.type = EntityType.PAGE;
        }
    }
  • Mail Obfuscation APIs: There are now 2 new APIs related to Email Address Obfuscation:

  • Configuration modifications: There's now a setProperties() API to modify ConfigurationSource properties. Scripting example:

    {{groovy}}
    import org.xwiki.configuration.*

    def cs = services.component.getInstance(ConfigurationSource.class, 'mailsend')
    cs.setProperties(['host' : 'localhost'])
    println cs.getProperty('host')
    {{/groovy}}
  • Configuration permissions: It's now possible to implement permission checking for ConfigurationSource properties, to decide who has the rights to view or modify them. To implement this check for your ConfigurationSource component, you need to implement the ConfigurationSourceAuthorization component role.

  • More locale-oriented APIs: We deprecated Document#getTranslationList() in favor of the new Document#getTranslationLocales() so if you have Velocity scripts using $doc.translationList you'll notice a deprecation warning in the server logs which you can avoid by using $doc.translationLocales instead.

    We also added XWiki#getAvailableLocales() so you can now replace

    $xwiki.getXWikiPreference('languages').split('\s*[|, ]\s*')

    with $xwiki.availableLocales in your Velocity scripts.

  • Deprecated Mail Script Services: The $services.mailsender and $services.mailstorage Script Service entry points have been deprecated in favor of $services.mail.sender and $services.mail.storage.

Upgrades

The following runtime dependencies have been upgraded (they have a different release cycle than XWiki Commons, XWiki Rendering and XWiki Platform):

Translations

The following translations have been updated: 

Tested Browsers & Databases

Here is the list of browsers we support and how they have been tested for this release:

 BrowserTested on:
Chrome30.pngGoogle Chrome 83Tests run and results
Firefox30.pngMozilla Firefox 76Jira Tickets Marked as Fixed in the Release Notes
Edge30.pngMicrosoft Edge 83Not Tested
IE30.pngInternet Explorer 11Not Tested
Safari30.pngSafari 13Not Tested

Here is the list of databases we support and how they have been tested for this release:

 DatabaseTested on:
hypersql.pngHyperSQL 2.5.0Not Tested
mysql.pngMySQL 5.7Not Tested
oracle.pngOracle 19cJira Tickets Marked as Fixed in the Release Notes
postgresql.pngPostgreSQL 12Not Tested
mariadb.pngMariaDB 10.4Tests run and results

Here is the list of Servlet Containers we support and how they have been tested for this release:

 Servlet ContainerTested on:
tomcat-icon.pngTomcat 9.0.31Jira Tickets Marked as Fixed in the Release Notes

Tests run and results
jetty-icon.pngJetty 9.4.27 (XWiki Standalone packaging)Not Tested
jetty-icon.pngJetty 9.4.27Not Tested

Known issues

Backward Compatibility and Migration Notes

General Notes

  • When upgrading make sure you compare and merge the following XWiki configuration files since some parameters may have been modified, removed or added:
    • xwiki.cfg
    • xwiki.properties
    • web.xml
    • hibernate.cfg.xml
  • Add xwiki.store.migration=1 in xwiki.cfg so that XWiki will attempt to automatically migrate your current database to any new schema. Make sure you backup your Database before doing anything.

API Breakages

The following APIs were modified since XWiki 12.3:

  • Wrongly placed extension. Breakage is limited
    • Violation type:
      java.annotation.removed
    • Code:
      ## Old:
      interface org.xwiki.xar.XarEntryTypeResolver

      ## New:
      interface org.xwiki.xar.XarEntryTypeResolver
  • Young API, not a breakage
    • Violation type:
      java.method.addedToInterface
    • Code:
      ## Old:
      null

      ## New:
      method void org.xwiki.user.UserProperties::save() throws org.xwiki.configuration.ConfigurationSaveException
  • Young API, not a breakage
    • Violation type:
      java.method.addedToInterface
    • Code:
      ## Old:
      null

      ## New:
      method void org.xwiki.user.UserProperties::setActive(boolean)
  • Young API, not a breakage
    • Violation type:
      java.method.addedToInterface
    • Code:
      ## Old:
      null

      ## New:
      method void org.xwiki.user.UserProperties::setDisplayHiddenDocuments(boolean)
  • Young API, not a breakage
    • Violation type:
      java.method.addedToInterface
    • Code:
      ## Old:
      null

      ## New:
      method void org.xwiki.user.UserProperties::setEditor(org.xwiki.user.Editor)
  • Young API, not a breakage
    • Violation type:
      java.method.addedToInterface
    • Code:
      ## Old:
      null

      ## New:
      method void org.xwiki.user.UserProperties::setEmail(javax.mail.internet.InternetAddress)
  • Young API, not a breakage
    • Violation type:
      java.method.addedToInterface
    • Code:
      ## Old:
      null

      ## New:
      method void org.xwiki.user.UserProperties::setEmailChecked(boolean)
  • Young API, not a breakage
    • Violation type:
      java.method.addedToInterface
    • Code:
      ## Old:
      null

      ## New:
      method void org.xwiki.user.UserProperties::setFirstName(java.lang.String)
  • Young API, not a breakage
    • Violation type:
      java.method.addedToInterface
    • Code:
      ## Old:
      null

      ## New:
      method void org.xwiki.user.UserProperties::setLastName(java.lang.String)
  • Young API, not a breakage
    • Violation type:
      java.method.addedToInterface
    • Code:
      ## Old:
      null

      ## New:
      method void org.xwiki.user.UserProperties::setType(org.xwiki.user.UserType)
  • Young API and should not have any impact on scripts
    • Violation type:
      java.method.parameterTypeChanged
    • Code:
      ## Old:
      parameter void com.xpn.xwiki.render.ScriptXWikiServletRequest::<init>(===javax.servlet.http.HttpServletRequest===, org.xwiki.security.authorization.ContextualAuthorizationManager)

      ## New:
      parameter void com.xpn.xwiki.render.ScriptXWikiServletRequest::<init>(===com.xpn.xwiki.web.XWikiRequest===, org.xwiki.security.authorization.ContextualAuthorizationManager)
  • Young API and should not have any impact on scripts
    • Violation type:
      java.method.removed
    • Code:
      ## Old:
      method javax.servlet.ServletRequest javax.servlet.ServletRequestWrapper::getRequest() @ com.xpn.xwiki.render.ScriptXWikiServletRequest
  • Young API and should not have any impact on scripts
    • Violation type:
      java.method.removed
    • Code:
      ## Old:
      method boolean javax.servlet.ServletRequestWrapper::isWrapperFor(java.lang.Class<?>) @ com.xpn.xwiki.render.ScriptXWikiServletRequest
  • Young API and should not have any impact on scripts
    • Violation type:
      java.method.removed
    • Code:
      ## Old:
      method boolean javax.servlet.ServletRequestWrapper::isWrapperFor(javax.servlet.ServletRequest) @ com.xpn.xwiki.render.ScriptXWikiServletRequest
  • Young API and should not have any impact on scripts
    • Violation type:
      java.method.removed
    • Code:
      ## Old:
      method void javax.servlet.ServletRequestWrapper::setRequest(javax.servlet.ServletRequest) @ com.xpn.xwiki.render.ScriptXWikiServletRequest
  • Young API and should not have any impact on scripts
    • Violation type:
      java.class.noLongerInheritsFromClass
    • Code:
      ## Old:
      class com.xpn.xwiki.render.ScriptXWikiServletRequest (archive = MavenArchive[gav=org.xwiki.platform:xwiki-platform-legacy-oldcore:jar:12.3, file=\/root\/.m2\/repository\/org\/xwiki\/platform\/xwiki-platform-legacy-oldcore\/12.3\/xwiki-platform-legacy-oldcore-12.3.jar], in api = true, through use = false)

      ## New:
      class com.xpn.xwiki.render.ScriptXWikiServletRequest (archive = MavenArchive[gav=org.xwiki.platform:xwiki-platform-legacy-oldcore:jar:12.4-SNAPSHOT, file=\/root\/workspace\/XWiki_xwiki-platform_master\/xwiki-platform-core\/xwiki-platform-legacy\/xwiki-platform-legacy-oldcore\/target\/xwiki-platform-legacy-oldcore-12.4-SNAPSHOT.jar], in api = true, through use = false)
  • Young API and should not have any impact on scripts
    • Violation type:
      java.class.nonFinalClassInheritsFromNewClass
    • Code:
      ## Old:
      class com.xpn.xwiki.render.ScriptXWikiServletRequest (archive = MavenArchive[gav=org.xwiki.platform:xwiki-platform-legacy-oldcore:jar:12.3, file=\/root\/.m2\/repository\/org\/xwiki\/platform\/xwiki-platform-legacy-oldcore\/12.3\/xwiki-platform-legacy-oldcore-12.3.jar], in api = true, through use = false)

      ## New:
      class com.xpn.xwiki.render.ScriptXWikiServletRequest (archive = MavenArchive[gav=org.xwiki.platform:xwiki-platform-legacy-oldcore:jar:12.4-SNAPSHOT, file=\/root\/workspace\/XWiki_xwiki-platform_master\/xwiki-platform-core\/xwiki-platform-legacy\/xwiki-platform-legacy-oldcore\/target\/xwiki-platform-legacy-oldcore-12.4-SNAPSHOT.jar], in api = true, through use = false)
  • Was never meant to be protected and the class did not made any sense, probably a bad copy/paste
    • Violation type:
      java.field.visibilityReduced
    • Code:
      ## Old:
      field com.xpn.xwiki.objects.BaseElement<R extends org.xwiki.model.reference.EntityReference>.LOGGER

      ## New:
      field com.xpn.xwiki.objects.BaseElement<R extends org.xwiki.model.reference.EntityReference>.LOGGER
  • Was never meant to be protected and the class did not made any sense, probably a bad copy/paste
    • Violation type:
      java.field.visibilityReduced
    • Code:
      ## Old:
      field com.xpn.xwiki.objects.BaseElement<R extends org.xwiki.model.reference.EntityReference>.LOGGER @ com.xpn.xwiki.objects.classes.BaseClass

      ## New:
      field com.xpn.xwiki.objects.classes.BaseClass.LOGGER
  • RequestFactory has been converted to an interface. Not breaking for using it as component.
    • Violation type:
      java.method.nowAbstract
    • Code:
      ## Old:
      method .+ org.xwiki.refactoring.script.RequestFactory::.+

      ## New:
      method .+ org.xwiki.refactoring.script.RequestFactory::.+
  • RequestFactory has been converted to an interface. Not breaking for using it as component.
    • Violation type:
      java.method.removed
    • Code:
      ## Old:
      method void org.xwiki.refactoring.script.RequestFactory::<init>()
  • RequestFactory has been converted to an interface. Not breaking for using it as component.
    • Violation type:
      java.method.removed
    • Code:
      ## Old:
      method .+ java.lang.Object::.+ @ org.xwiki.refactoring.script.RequestFactory
  • As part of the refactoring of RequestFactory to transform it as an interface, this method has been made private.
    • Violation type:
      java.method.removed
    • Code:
      ## Old:
      method void org.xwiki.refactoring.script.RequestFactory::setRightsProperties(org.xwiki.job.api.AbstractCheckRightsRequest)
  • RequestFactory has been converted to an interface. Not breaking for using it as component.
    • Violation type:
      java.class.kindChanged
    • Code:
      ## Old:
      class org.xwiki.refactoring.script.RequestFactory

      ## New:
      interface org.xwiki.refactoring.script.RequestFactory
  • RequestFactory has been converted to an interface. Not breaking for using it as component.
    • Violation type:
      java.class.nowAbstract
    • Code:
      ## Old:
      class org.xwiki.refactoring.script.RequestFactory

      ## New:
      interface org.xwiki.refactoring.script.RequestFactory
  • RequestFactory has been converted to an interface. Not breaking for using it as component.
    • Violation type:
      java.annotation.removed
    • Code:
      ## Old:
      class org.xwiki.refactoring.script.RequestFactory

      ## New:
      interface org.xwiki.refactoring.script.RequestFactory
  • RequestFactory has been converted to an interface. Not breaking for using it as component.
    • Violation type:
      java.annotation.removed
    • Code:
      ## Old:
      class org.xwiki.refactoring.script.RequestFactory

      ## New:
      interface org.xwiki.refactoring.script.RequestFactory
  • RequestFactory has been converted to an interface. Not breaking for using it as component.
    • Violation type:
      java.annotation.added
    • Code:
      ## Old:
      class org.xwiki.refactoring.script.RequestFactory

      ## New:
      interface org.xwiki.refactoring.script.RequestFactory
  • EditorDescriptorBuilder has been converted to an interface. Not breaking for using it as component.
    • Violation type:
      java.method.nowAbstract
    • Code:
      ## Old:
      method .+ org.xwiki.edit.EditorDescriptorBuilder::.+

      ## New:
      method .+ org.xwiki.edit.EditorDescriptor(Builder)?::.+( @ org.xwiki.edit.EditorDescriptorBuilder)?
  • EditorDescriptorBuilder has been converted to an interface. Not breaking for using it as component.
    • Violation type:
      java.method.removed
    • Code:
      ## Old:
      method void org.xwiki.edit.EditorDescriptorBuilder::<init>()
  • EditorDescriptorBuilder has been converted to an interface. Not breaking for using it as component.
    • Violation type:
      java.method.removed
    • Code:
      ## Old:
      method .+ java.lang.Object::.+ @ org.xwiki.edit.EditorDescriptorBuilder
  • EditorDescriptorBuilder has been converted to an interface. Not breaking for using it as component.
    • Violation type:
      java.class.kindChanged
    • Code:
      ## Old:
      class org.xwiki.edit.EditorDescriptorBuilder

      ## New:
      interface org.xwiki.edit.EditorDescriptorBuilder
  • EditorDescriptorBuilder has been converted to an interface. Not breaking for using it as component.
    • Violation type:
      java.class.nowAbstract
    • Code:
      ## Old:
      class org.xwiki.edit.EditorDescriptorBuilder

      ## New:
      interface org.xwiki.edit.EditorDescriptorBuilder
  • EditorDescriptorBuilder has been converted to an interface. Not breaking for using it as component.
    • Violation type:
      java.annotation.removed
    • Code:
      ## Old:
      class org.xwiki.edit.EditorDescriptorBuilder

      ## New:
      interface org.xwiki.edit.EditorDescriptorBuilder
  • EditorDescriptorBuilder has been converted to an interface. Not breaking for using it as component.
    • Violation type:
      java.annotation.removed
    • Code:
      ## Old:
      class org.xwiki.edit.EditorDescriptorBuilder

      ## New:
      interface org.xwiki.edit.EditorDescriptorBuilder
  • EditorDescriptorBuilder has been converted to an interface. Not breaking for using it as component.
    • Violation type:
      java.annotation.added
    • Code:
      ## Old:
      class org.xwiki.edit.EditorDescriptorBuilder

      ## New:
      interface org.xwiki.edit.EditorDescriptorBuilder
  • EditorDescriptorBuilder has been converted to an interface. Not breaking for using it as component.
    • Violation type:
      java.annotation.removed
    • Code:
      ## Old:
      class org.xwiki.edit.EditorDescriptorBuilder

      ## New:
      interface org.xwiki.edit.EditorDescriptorBuilder

Issues specific to XWiki 12.4

We changed the behaviour of this kind of URLs: myxwiki/edit/MyPage/?editor=object&xaction=objectAdd. This xaction parameter used to save the added xobjects, but it's not the case anymore. Please refer to this documentation for adding xobject to a page.

Credits

The following people have contributed code and translations to this release (sorted alphabetically):

  • Clemens Robbenhaar
  • Manuel Leduc
  • Marius Dumitru Florea
  • Simon Urli
  • Thomas Mortagne
  • Usama ahmad
  • Vincent Massol
  • xrichard

Get Connected