Page template labels can not be saved when an incremental sync subscription is active.

XMLWordPrintable

    • 1
    • Severity 3 - Minor
    • RtB - Service ops & Tech entropy

      Issue Summary

      Adding or removing labels on page templates fails with a 500 Internal Server Error when at least one content management incremental sync subscription (containing the 'PAGE_EVENT' type) is active.

      This affects both creating new templates with labels and editing existing templates to add/remove labels. Labels on regular pages and blog posts are unaffected.

      Steps to Reproduce

      Path 1 — Creating a new template

       1.  Create a subscription (see section below)
       2.  Create a page template and add labels to it
       3.  Save the template
       4.  At this stage, it will look like it has succeeded, but in reality will silently fail. The new template will be absent from the list entirely.

      Path 2 — Updating an existing template

       1.  Create a subscription (see section below)
       2.  Create a page template without any labels, save it.
       3.  Edit the page template and try to add a label to it.
       4.  This will trigger the error as long as at least one subscription exists.

      Create a subscription
      The crucial part is setting up an incremental sync subscription. We can do this easily enough with a few REST API calls. These examples are using basic auth because it is quick and easy, but any valid authentication method should work. Crucially, the subscription must contain PAGE_EVENT as a type, as this includes page template updates.

      curl -u $USER:$PASSWORD -X POST \
        "$CONFLUENCE_BASE_URL/rest/internal/sync/latest/contentmanagement/event/subscription" \
        -H "Content-Type: application/json" \
        -d '{"types": ["PAGE_EVENT"]}' 

      It may also be useful to know the endpoints to list and delete subscriptions to compare before and after:

      List subscriptions

      curl -u $USER:$PASSWORD \
        "$CONFLUENCE_BASE_URL/rest/internal/sync/latest/contentmanagement/event/subscriptions"

      Delete subscription by ID
      You can get the ID in the response from the original create request, or by using the list endpoint (above), OR by inspecting the `INCREMENTAL_SYNC_SUBSCRIPTION` database table.

      curl -u $USER:$PASSWORD -X DELETE \
        "$CONFLUENCE_BASE_URL/rest/internal/sync/latest/contentmanagement/event/subscription/$SUBSCRIPTION_ID" 

      Expected Results

      Path 1 — Creating a new template

      The new template is saved and includes the labels.

      Path 2— Updating an existing template

      The template is updated to include the new labels.

      Actual Results

      Path 1 — Creating a new template

      The creation of the template silently fails. No new template will appear in the list and nothing will be be saved.

      Path 2 — Updating an existing template

      Updating the template will visibly fail and provide a traceID for log analysis.

      In both cases, an exception is thrown in the logs and the transaction is rolled back.

      ERROR [http-nio-8080-exec-3] [service.incrementalsync.AbstractRecorder] handleEvent Failed to handle event com.atlassian.confluence.event.events.label.LabelAddEvent[source=test] for user management incremental syncjava.lang.ClassCastException: class com.atlassian.confluence.pages.templates.PageTemplate cannot be cast to class com.atlassian.confluence.core.ContentEntityObject (com.atlassian.confluence.pages.templates.PageTemplate and com.atlassian.confluence.core.ContentEntityObject are in unnamed module of loader org.apache.catalina.loader.ParallelWebappClassLoader @7008055)	at com.atlassian.confluence.internal.api.impl.service.incrementalsync.contentmanagement.commands.AbstractLabelCommand.processEvent(AbstractLabelCommand.java:52)	at com.atlassian.confluence.internal.api.impl.service.incrementalsync.contentmanagement.commands.AbstractLabelCommand.processEvent(AbstractLabelCommand.java:35)	at com.atlassian.confluence.internal.api.impl.service.incrementalsync.contentmanagement.ContentManagementRecorder.lambda$executeCommand$0(ContentManagementRecorder.java:262)	at com.atlassian.confluence.internal.api.impl.service.incrementalsync.contentmanagement.ContentManagementIncrementalSyncServiceImpl.lambda$handleEventForSubscription$3(ContentManagementIncrementalSyncServiceImpl.java:162)	at com.atlassian.confluence.internal.api.impl.service.incrementalsync.contentmanagement.ContentManagementIncrementalSyncServiceImpl.handleEventForSubscription(ContentManagementIncrementalSyncServiceImpl.java:156)	at com.atlassian.confluence.internal.api.impl.service.incrementalsync.contentmanagement.ContentManagementRecorder.executeCommand(ContentManagementRecorder.java:259)	at com.atlassian.confluence.internal.api.impl.service.incrementalsync.AbstractRecorder.lambda$handleEvent$0(AbstractRecorder.java:33)	at com.atlassian.confluence.internal.api.impl.service.incrementalsync.AbstractRecorder.lambda$executeWithTransaction$3(AbstractRecorder.java:50)	at com.atlassian.confluence.internal.api.impl.service.incrementalsync.AbstractRecorder.handleEvent(AbstractRecorder.java:33)	at com.atlassian.confluence.internal.api.impl.service.incrementalsync.contentmanagement.ContentManagementRecorder.onLabelAddEvent(ContentManagementRecorder.java:249)
      WARN [http-nio-8080-exec-3] [impl.hibernate.ConfluenceHibernateTransactionManager] doRollback Performing rollback. Transactions:  ->[com.atlassian.confluence.labels.service.AddLabelsCommandImpl.execute]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
      ERROR [http-nio-8080-exec-3] [api.model.ExceptionConverter] convertServiceException No status code found for exception, converting to internal server error.org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only	at org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.java:938)	at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:754)	at com.atlassian.confluence.labels.DefaultLabelManager.addLabel(DefaultLabelManager.java:93)	at com.atlassian.confluence.impl.labels.CachingLabelManager.addLabel(CachingLabelManager.java:109) 

      Workaround

      Currently the only known workaround is to disable or remove the incremental sync subscription, which can be done with the API calls mentioned in Steps to Reproduce. 

      Admins can inspect the `INCREMENTAL_SYNC_SUBSCRIPTION` table in the database to understand their instance's subscriptions.

      This can also be achieved by changing subscription states to INACTIVE in the same table.

      However while disabled, all content change events for this subscription will be silently dropped, meaning a full re-sync is required to realign the consumer's state.

              Assignee:
              Tom Smallridge
              Reporter:
              Tom Smallridge
              Votes:
              1 Vote for this issue
              Watchers:
              3 Start watching this issue

                Created:
                Updated:
                Resolved: