Edit online

Integrating Concurrent Editing

Oxygen XML Web Author provides the ability for teams to edit and review content concurrently. A user can share their editing session by using the Share Session toolbar button and then sending the retrieved URL to other collaborators and then all of them can edit and review the same document simultaneously.

Edit online

Enabling the Share Session Action

To enable the Share Session action, the following conditions must be met:

  • The Concurrent Editing Plugin must be enabled in the Administration Page (it is bundled with the Oxygen XML Web Author installers so it is enabled by default).
  • The sharedSessionCompatible loading option is set to true by the CMS connector plugin.

For the feature to work correctly, when a concurrent session is active, the CMS connector plugin should ensure that:

  • Any save/commit action is disabled for session guests.
  • Any check-in/check-out actions are disabled for session guests.
  • The document is editable for guests even though they do not have a lock for it.
To detect that a user is a guest, you can use the following JavaScript code:
var mgr = editor.getEditingSupport().getConcurrentEditingManager();    
if (mgr && !mgr.isCreator()) {      
      ...
} 
Important Notes About Concurrent Editing for Integrators:
  • Concurrent editing does not work if Oxygen XML Web Author is deployed on multiple servers behind a load balancer.
  • Oxygen XML Web Author uses Web Sockets to propagate changes in real time between collaborators. If you are using a reverse proxy, some additional configuration may be required to enable Web Socket connections to the ./ws endpoint of the application.

    For example, NGINX requires the following configuration for the /oxygen-xml-web-author/ws path:
    location /oxygen-xml-web-author/ws {
      proxy_http_version 1.1;
          
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
      proxy_set_header Host $host;
          
      proxy_pass http://web-author:8080;
    }

    As another example, when using Apache HTTP server as a reverse proxy, a system administrator needs to enable the following modules:

    • rewrite

    • proxy_http

    • proxy_wstunnel

    Also, a configuration similar to the one below should be added:
    ProxyPass /oxygen-xml-web-author http://<internal-host>:8080/oxygen-xml-web-author
    ProxyPassReverse /oxygen-xml-web-author http://<internal-host>:8080/oxygen-xml-web-author
    
    RewriteEngine on
    RewriteCond %{​HTTP:Upgrade}​ websocket [NC]
    RewriteCond %{​HTTP:Connection}​ upgrade [NC]
    RewriteRule ^/oxygen-xml-web-author/?(.*) 
     "ws://<internal-host>:8080/oxygen-xml-web-author/$1" [P,L]

    When using the IIS web server as a reverse proxy, you need to configure it according to this tutorial.

  • Some customizations can cause problems if used in situations with high activity or a large number of users simultaneously. These possible limitations include:
    • The onChange property for the combo box form control is not supported in concurrent editing sessions.
    • Inline CSS actions (for example, when used in an oxy_button form control).
    • Editable combo boxes on the floating toolbar.
    • Quick fixes that come from XML Schema or DTD.

Disabling the Share Session Action

To remove the Share Session action from the toolbar, simply disable the Concurrent Editing Plugin in the Administration Page.

Edit online

CMS-owned Concurrent Editing Sessions

Aside from using the Share Session action, a more integrated concurrent editing approach is to have a concurrent editing room owned by the CMS.

The CMS should be responsible for:
  • Ensuring that aside from the Web Author users, no other users are modifying the file. The CMS can use a "service" account to hold the "lock" on the edited file, or to do a check-out.
  • Creating the concurrent editing room.
  • Enabling users to join the room.
  • Specifying the Save Strategy.
  • Closing the room.

Creating a Concurrent Editing Room

The CMS can use the following JavaScript code to create a concurrent editing room:
editor.getEditingSupport().getConcurrentEditingManager().createRoom().then(roomId =>
window.open(window.location.href + '&roomId=' + roomId))

The ID of the room can then be shared with other users. To join an existing room, the roomId URL parameter can be used.

By using the Java API, a room can be created like this:

String roomId = RoomsManager.INSTANCE.createRoomFromDocument(AuthorDocumentModel) 

This code can be used during the editor loading on the following callbacks:

  • ro.sync.ecss.extensions.api.webapp.access.WebappEditingSessionLifecycleListener.editingSessionAboutToBeStarted(). In this case, the room ID has to be added to the sessionAttributes map using the ro.sync.ecss.extensions.api.webapp.ce.Room.ROOM_ID_ATTRIBUTE key.
  • ro.sync.ecss.extensions.api.webapp.access.WebappEditingSessionLifecycleListener.editingSessionStarted(). In this case, the room ID has to be added as an attribute to the editing context of the current document using ro.sync.ecss.extensions.api.webapp.ce.Room.ROOM_ID_ATTRIBUTE as the name. The editing context can be obtained by calling: authorDocumentModel.getAuthorAccess().getEditorAccess().getEditingContext().

Saving a Concurrent Editing Session

When saving a concurrently edited document, the application uses a save strategy that can be specified when creating the room by calling ro.sync.ecss.extensions.api.webapp.ce.RoomFactory.createRoom(AuthorDocumentModel, SaveStrategy).

The save strategy specifies what gets written to the CMS. Either the changed document is saved for each peer individually or all changes since the last save are grouped and written to the CMS only once. Additionally, it provides the URLConnection for the OutputStream where the changes from an author or from a list of author are written.

There are two base classes to be extended:
  1. ro.sync.ecss.extensions.api.webapp.ce.GroupChangesForSinglePeerStrategy - It facilitates tracking precise authorship of changes, as each written revision contains changes by only one author.
    Note: The URLConnection openConnection(URL documentUrl, PeerContext author) method has only one peer involved, being both the author and the committer.
  2. ro.sync.ecss.extensions.api.webapp.ce.GroupChangesForMultiplePeersStrategy - It facilitates a minimum number of writes to the file server per save.
    Note: The URLConnection openConnection(URL documentUrl, PeerContext committer, List<PeerContext> authors) method has a committer and a list of authors, whose changes are grouped together.

Enabling Users to Join a Room

To enable users to join a room, there are several options:

  • Add roomId=<the-id> as a URL parameter.
  • Add roomId=<the-id> as a loading option in a JavaScript plugin.
  • Set roomId=<the-id> as a session attribute in one of the following Java listeners:
    • ro.sync.ecss.extensions.api.webapp.access.WebappEditingSessionLifecycleListener.editingSessionAboutToBeStarted()
    • ro.sync.ecss.extensions.api.webapp.access.WebappEditingSessionLifecycleListener.editingSessionStarted()

Closing the Room

A room created this way is not closed when the last user leaves. It should be closed using Room.close() when all the users have left and all the changes are saved.