Uploaded image for project: 'Confluence Data Center'
  1. Confluence Data Center
  2. CONFSERVER-30411

Gliffy stops working on other cluster nodes after re-enablement

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: Medium Medium
    • 5.5.1
    • 4.3.7, 5.2.3
    • None
    • Confluence Gliffy Plugin 5.4.2

      This was also reported to be failing with the Confluence Gliffy Plugin 5.4 on Confluence 3.5.17.

      1. two node cluster setup
      2. install the Confluence Gliffy Plugin on one node (called producer node from now on)
      3. ensure that the plugin and it's state was successfully synced by visiting /plugins/servlet/upm#manage on the other node (called consumer node from now on)
      4. disable the plugin on the producer node
      5. ensure that the disabled state got synced on the consumer node
      6. re-enable the plugin on the producer node
      7. refresh /plugins/servlet/upm#manage again on the consumer node

      You will see that the producer node shows "89 of 89 modules enabled" and the consumer node shows "88 of 88 modules enabled" for that plugin.

      Also when the plugin is disabled, both nodes will show "0 of 88 modules enabled". The missing module is the "Rest Servlet Filter(gliffy-api-rest-filter)". Note that the missing module is not part of the atlassian-plugin.xml descriptor and seems to be added dynamically by the RestModuleDescriptor.

      I've constructed a minimal plugin

      <atlassian-plugin key="rest-test" plugins-version="2">
      	<rest key="rest-rest" path="/rest/test" version="1.0"/>
      </atlassian-plugin>
      

      and put this in a file named atlassian-plugin.xml and compressed it with the zip algorithm into the attached rest-test.jar. But if I install this plugin via UPM into the cluster and disable/enable it, the state gets correctly propagated and the receiving node will still have a Rest Servlet Filter(rest-rest-filter) module.

        1. rest-test.jar
          0.3 kB
        2. Selection_123.png
          Selection_123.png
          188 kB
        3. Selection_124.png
          Selection_124.png
          17 kB
        4. Selection_127.png
          Selection_127.png
          158 kB

            [CONFSERVER-30411] Gliffy stops working on other cluster nodes after re-enablement

            Fresh install still requires restart of consumer nodes.

            It should be noted that this is due to CONF-9281 and it will be worked on soonish?

            fabs (Inactive) added a comment - Fresh install still requires restart of consumer nodes. It should be noted that this is due to CONF-9281 and it will be worked on soonish?

            Gliffy Plugin is correctly propagated across nodes as well as the individual plugin modules. Fresh install still requires restart of consumer nodes.

            Glenn Martin (Inactive) added a comment - Gliffy Plugin is correctly propagated across nodes as well as the individual plugin modules. Fresh install still requires restart of consumer nodes.

            Glenn to test this.

            Glenn Martin (Inactive) added a comment - Glenn to test this.

            As written above, a potential workaround at the moment is to uninstall and then reinstall Gliffy, which means that the first stack is caused leading to the correct enablement of all modules. The Gliffy license does not have to be re-installed.

            fabs (Inactive) added a comment - As written above, a potential workaround at the moment is to uninstall and then reinstall Gliffy, which means that the first stack is caused leading to the correct enablement of all modules. The Gliffy license does not have to be re-installed.

            com.atlassian.plugin.ModuleDescriptor<T> are allowed to become aware of their activation state via com.atlassian.plugin.StateAware. This state propagation currently can't work in the cluster.

            RestModuleDescriptor.enabled() line: 166	
            	ConfluencePluginManager(DefaultPluginManager).notifyModuleEnabled(ModuleDescriptor<?>) line: 1573	
            	ConfluencePluginManager.notifyModuleEnabled(ModuleDescriptor<?>) line: 135	
            	ConfluencePluginManager(DefaultPluginManager).enableConfiguredPluginModule(Plugin, ModuleDescriptor<?>, Set<ModuleDescriptor<?>>) line: 1376	
            	ConfluencePluginManager(DefaultPluginManager).enableConfiguredPluginModules(Plugin) line: 1343	
            	ConfluencePluginManager(DefaultPluginManager).addPlugins(PluginLoader, Collection<Plugin>) line: 815	
            	ConfluencePluginManager.addPlugins(PluginLoader, Collection<Plugin>) line: 236	
            	ConfluencePluginManager(DefaultPluginManager).scanForNewPlugins() line: 521	
            	ConfluencePluginManager.processClusteredInstallEvent(PluginEvent) line: 387	
            	ConfluencePluginManager.processPluginEvent(PluginEvent) line: 326	
            	ConfluencePluginManager.onApplicationEvent(ApplicationEvent) line: 285	
            	SimpleApplicationEventMulticaster$1.run() line: 78	
            	SyncTaskExecutor.execute(Runnable) line: 49	
            	SimpleApplicationEventMulticaster.multicastEvent(ApplicationEvent) line: 76	
            	ConfluenceXmlWebApplicationContext(AbstractApplicationContext).publishEvent(ApplicationEvent) line: 274	
            	SpringContextEventPublisher.handleEvent(Event) line: 22	
            	LegacyListenerHandler$LegacyListenerInvoker.invoke(Object) line: 55	
            	AsynchronousAbleEventDispatcher$2.run() line: 66	
            	AsynchronousAbleEventDispatcher$1.execute(Runnable) line: 32	
            	AsynchronousAbleEventDispatcher.dispatch(ListenerInvoker, Object) line: 60	
            	EventPublisherImpl.invokeListeners(Collection<KeyedListenerInvoker>, Object) line: 160	
            	EventPublisherImpl.publish(Object) line: 79	
            	LegacyEventManager.publishEvent(Event) line: 36	
            	ConfluenceEventManager.publishEvent(Event) line: 47	
            	...
            	EventInvocable.run() line: 41	
            	InvocationService.onInvocationMessage(InvocationService$InvocationMessage) line: 6	
            	InvocationService$InvocationMessage.run() line: 1	
            	...
            

            This stack shows how the module gets enabled during installation on a consuming node. If the plugin gets re-enabled, ConfluencePluginManager(DefaultPluginManager).enableConfiguredPluginModule(Plugin, ModuleDescriptor<?>, Set<ModuleDescriptor<?>>) line: 1376 is not hit.

            cePluginManager(DefaultPluginManager).enableConfiguredPluginModule(Plugin, ModuleDescriptor<?>, Set<ModuleDescriptor<?>>) line: 1373	
            	ConfluencePluginManager(DefaultPluginManager).enableConfiguredPluginModules(Plugin) line: 1343	
            	ConfluencePluginManager(DefaultPluginManager).notifyPluginEnabled(Plugin) line: 1321	
            	ConfluencePluginManager.notifyPluginEnabled(Plugin) line: 114	
            	ConfluencePluginManager.processPluginEvent(PluginEvent) line: 345	
            	ConfluencePluginManager.onApplicationEvent(ApplicationEvent) line: 285	
            	SimpleApplicationEventMulticaster$1.run() line: 78	
            	SyncTaskExecutor.execute(Runnable) li
            ne: 49	
            	SimpleApplicationEventMulticaster.multicastEvent(ApplicationEvent) line: 76	
            	ConfluenceXmlWebApplicationContext(AbstractApplicationContext).publishEvent(ApplicationEvent) line: 274	
            	SpringContextEventPublisher.handleEvent(Event) line: 22	
            	LegacyListenerHandler$LegacyListenerInvoker.invoke(Object) line: 55	
            	AsynchronousAbleEventDispatcher$2.run() line: 66	
            	AsynchronousAbleEventDispatcher$1.execute(Runnable) line: 32	
            	AsynchronousAbleEventDispatcher.dispatch(ListenerInvoker, Object) line: 60	
            	EventPublisherImpl.invokeListeners(Collection<KeyedListenerInvoker>, Object) line: 160	
            	EventPublisherImpl.publish(Object) line: 79	
            	LegacyEventManager.publishEvent(Event) line: 36	
            	ConfluenceEventManager.publishEvent(Event) line: 47	
                    ...
            	EventInvocable.run() line: 41	
            	InvocationService.onInvocationMessage(InvocationService$InvocationMessage) line: 6	
            	InvocationService$InvocationMessage.run() line: 1	
                    ...
            

            The frame will return on this line, since the module is already enabled (l1364-1374).

                        // We only want to re-enable modules that weren't explicitly
                        // disabled by the user.
                        if (!isPluginModuleEnabled(descriptor.getCompleteKey()))
                        {
                            if (log.isDebugEnabled())
                            {
                                String name = descriptor.getName() == null ? descriptor.getKey() : descriptor.getName();
                                log.debug("Plugin module '" + name + "' is explicitly disabled (or so by default), so not re-enabling.");
                            }
                            return success;
                        }
            

            This is due to the database-backed com.atlassian.confluence.plugin.BandanaPluginStateStore. The com.atlassian.confluence.plugin.EventDispatchingPluginController is supposed to work around this in the cluster. If com.atlassian.confluence.plugin.ConfluencePluginManager.onApplicationEvent(ApplicationEvent) receives a ClusterEventWrapper containing a PluginModuleEnableEvent, com.atlassian.confluence.plugin.ConfluencePluginManager.notifyModuleEnabled(ModuleDescriptor<?>) is called leading to the com.atlassian.plugin.StateAware.enabled() call.

            Thus the approach to support StateAware for modules in the cluster is to capture plugin state changes in com.atlassian.confluence.plugin.EventDispatchingPluginController and capture PluginModuleEnabledEvents/PluginModuleDisabledEvents during that operation and dispatch them as PluginModuleEnableEvents/PluginModuleDisableEvent in the cluster after the delegate succeeds.

            fabs (Inactive) added a comment - com.atlassian.plugin.ModuleDescriptor<T> are allowed to become aware of their activation state via com.atlassian.plugin.StateAware . This state propagation currently can't work in the cluster. RestModuleDescriptor.enabled() line: 166 ConfluencePluginManager(DefaultPluginManager).notifyModuleEnabled(ModuleDescriptor<?>) line: 1573 ConfluencePluginManager.notifyModuleEnabled(ModuleDescriptor<?>) line: 135 ConfluencePluginManager(DefaultPluginManager).enableConfiguredPluginModule(Plugin, ModuleDescriptor<?>, Set<ModuleDescriptor<?>>) line: 1376 ConfluencePluginManager(DefaultPluginManager).enableConfiguredPluginModules(Plugin) line: 1343 ConfluencePluginManager(DefaultPluginManager).addPlugins(PluginLoader, Collection<Plugin>) line: 815 ConfluencePluginManager.addPlugins(PluginLoader, Collection<Plugin>) line: 236 ConfluencePluginManager(DefaultPluginManager).scanForNewPlugins() line: 521 ConfluencePluginManager.processClusteredInstallEvent(PluginEvent) line: 387 ConfluencePluginManager.processPluginEvent(PluginEvent) line: 326 ConfluencePluginManager.onApplicationEvent(ApplicationEvent) line: 285 SimpleApplicationEventMulticaster$1.run() line: 78 SyncTaskExecutor.execute( Runnable ) line: 49 SimpleApplicationEventMulticaster.multicastEvent(ApplicationEvent) line: 76 ConfluenceXmlWebApplicationContext(AbstractApplicationContext).publishEvent(ApplicationEvent) line: 274 SpringContextEventPublisher.handleEvent(Event) line: 22 LegacyListenerHandler$LegacyListenerInvoker.invoke( Object ) line: 55 AsynchronousAbleEventDispatcher$2.run() line: 66 AsynchronousAbleEventDispatcher$1.execute( Runnable ) line: 32 AsynchronousAbleEventDispatcher.dispatch(ListenerInvoker, Object ) line: 60 EventPublisherImpl.invokeListeners(Collection<KeyedListenerInvoker>, Object ) line: 160 EventPublisherImpl.publish( Object ) line: 79 LegacyEventManager.publishEvent(Event) line: 36 ConfluenceEventManager.publishEvent(Event) line: 47 ... EventInvocable.run() line: 41 InvocationService.onInvocationMessage(InvocationService$InvocationMessage) line: 6 InvocationService$InvocationMessage.run() line: 1 ... This stack shows how the module gets enabled during installation on a consuming node. If the plugin gets re-enabled, ConfluencePluginManager(DefaultPluginManager).enableConfiguredPluginModule(Plugin, ModuleDescriptor<?>, Set<ModuleDescriptor<?>>) line: 1376 is not hit. cePluginManager(DefaultPluginManager).enableConfiguredPluginModule(Plugin, ModuleDescriptor<?>, Set<ModuleDescriptor<?>>) line: 1373 ConfluencePluginManager(DefaultPluginManager).enableConfiguredPluginModules(Plugin) line: 1343 ConfluencePluginManager(DefaultPluginManager).notifyPluginEnabled(Plugin) line: 1321 ConfluencePluginManager.notifyPluginEnabled(Plugin) line: 114 ConfluencePluginManager.processPluginEvent(PluginEvent) line: 345 ConfluencePluginManager.onApplicationEvent(ApplicationEvent) line: 285 SimpleApplicationEventMulticaster$1.run() line: 78 SyncTaskExecutor.execute( Runnable ) li ne: 49 SimpleApplicationEventMulticaster.multicastEvent(ApplicationEvent) line: 76 ConfluenceXmlWebApplicationContext(AbstractApplicationContext).publishEvent(ApplicationEvent) line: 274 SpringContextEventPublisher.handleEvent(Event) line: 22 LegacyListenerHandler$LegacyListenerInvoker.invoke( Object ) line: 55 AsynchronousAbleEventDispatcher$2.run() line: 66 AsynchronousAbleEventDispatcher$1.execute( Runnable ) line: 32 AsynchronousAbleEventDispatcher.dispatch(ListenerInvoker, Object ) line: 60 EventPublisherImpl.invokeListeners(Collection<KeyedListenerInvoker>, Object ) line: 160 EventPublisherImpl.publish( Object ) line: 79 LegacyEventManager.publishEvent(Event) line: 36 ConfluenceEventManager.publishEvent(Event) line: 47 ... EventInvocable.run() line: 41 InvocationService.onInvocationMessage(InvocationService$InvocationMessage) line: 6 InvocationService$InvocationMessage.run() line: 1 ... The frame will return on this line, since the module is already enabled (l1364-1374). // We only want to re-enable modules that weren't explicitly // disabled by the user. if (!isPluginModuleEnabled(descriptor.getCompleteKey())) { if (log.isDebugEnabled()) { String name = descriptor.getName() == null ? descriptor.getKey() : descriptor.getName(); log.debug( "Plugin module '" + name + "' is explicitly disabled (or so by default ), so not re-enabling." ); } return success; } This is due to the database-backed com.atlassian.confluence.plugin.BandanaPluginStateStore . The com.atlassian.confluence.plugin.EventDispatchingPluginController is supposed to work around this in the cluster. If com.atlassian.confluence.plugin.ConfluencePluginManager.onApplicationEvent(ApplicationEvent) receives a ClusterEventWrapper containing a PluginModuleEnableEvent , com.atlassian.confluence.plugin.ConfluencePluginManager.notifyModuleEnabled(ModuleDescriptor<?>) is called leading to the com.atlassian.plugin.StateAware.enabled() call. Thus the approach to support StateAware for modules in the cluster is to capture plugin state changes in com.atlassian.confluence.plugin.EventDispatchingPluginController and capture PluginModuleEnabledEvents/PluginModuleDisabledEvents during that operation and dispatch them as PluginModuleEnableEvents/PluginModuleDisableEvent in the cluster after the delegate succeeds.

              onevalainen Olli Nevalainen
              fakraemer fabs (Inactive)
              Affected customers:
              3 This affects my team
              Watchers:
              7 Start watching this issue

                Created:
                Updated:
                Resolved: