Techblog

Herzlich Willkommen im Communardo Techblog, dem Entwickler-Weblog von Communardo. An dieser Stelle werden Ideen, Problemlösungen, Tipps und Problemstellungen rund um die Entwicklung webbasierter Software vorgestellt.

techblog-teaser

Workaround für Bug im Trigger Modultyp

, von
1 Kommentar

Seit Confluence 2.10 gibt es einen ziemlich unangenehmen Bug im Trigger-Plugin-Modultyp:

Manchmal kommt es vor, dass ein Plugin bei der Installation nicht erfolgreich aktiviert werden kann. In diesem Fall werden alle Module deaktiviert, also auch der Trigger. Dabei wird aber auch versucht den zugehörigen Job zu deaktivieren. Ist der zu dem Zeitpunkt noch nicht vollständig geladen, kommt es zu einer IllegalStateException. In der Folge befindet sich das Plugin in einer Art “Zwischenzustand”. Es erscheint zwar als installiert und aktiviert in der Pluginübersicht, aber keine der vom Plugin bereitgestellt Funktionen sind verfügbar. Außerdem kann das Plugin erst nach einem Neustart von Confluence aus dem System entfernt werden. Jeder Versuch es ohne Neustart zu deinstallieren wird mit einer org.springframework.orm.ObjectRetrievalFailureException quittiert.

Da dieses Problem die Wartung von Kundeninstallationen und Nightly Builds erheblich erschwert, musste ein Workaround her. Da es seit Confluence 2.10 die Möglichkeit gibt eigene Plugin Modultypen zu definieren indem man den neuen Module-Type-Modultyp verwendet, war es relativ einfach eine Lösung zu finden, die sogar als Plugin installiert werden kann (keine Anpassung des Confluence Kerns nötig!): Man definiert einen Modultyp, der von TriggerModuleDescriptor (der Implemetation des Trigger-Plugin-Modultyps) erbt. Dort überschreibt man die Methode disabled(), deren Aufruf die Exception verursacht:

public class RobustTriggerModuleDescriptor extends TriggerModuleDescriptor {

    /**
     * Logger for this class.
     */
    static Logger LOG = Logger.getLogger(RobustTriggerModuleDescriptor.class);
    static final String WARN_MESSAGE = "Using workaround for CONF-14828. "+
         "Code might be deprecated.";
    static final String ERROR_MESSAGE = "Disabling of module failed.";

    public void init(final Plugin plugin, final Element element)
      throws PluginParseException {
        Scheduler sched = (Scheduler) ContainerManager.getComponent("scheduler");
        setScheduler(sched);
        super.init(plugin, element);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void disabled() {
        try {
            super.disabled();
        } catch (IllegalStateException e) {
            LOG.warn(WARN_MESSAGE);
            try {
                // using reflection to replicate behavior of
                // AbstractModuleDescriptor.disabled()
                // as the call to this method was suppressed by
                // the exception and there is no way
                // to call super.super.disabled()
                Field enabledField = AbstractModuleDescriptor.class
                        .getDeclaredField("enabled");
                enabledField.setAccessible(true);
                enabledField.set(this, false);
                Field moduleClassField = AbstractModuleDescriptor.class
                        .getDeclaredField("moduleClass");
                moduleClassField.setAccessible(true);
                moduleClassField.set(this, null);
            } catch (Exception e1) {
                LOG.error(ERROR_MESSAGE, e1);
            }
        }
    }

}

Die Methode init() wurde überschrieben um die vom Trigger benötigte Scheduler-Bean zu injizieren. Im TriggerModuleDescriptor wird diese Bean durch Autowiring automatisch gesetzt. Da der abgeleitete RobustTriggerModuleDescriptor aber ein anderer Modultyp ist, findet bei dessen Initialisierung kein Autowiring statt.

Um den neuen Modultyp nutzen zu können, muss man ihn zunächst im Plugin-Descriptor (atlassian-plugin.xml) konfigurieren:

<module-type name="Robust Trigger Module Descriptor" key="robust-trigger"
class="your.fancy.package.name.RobustTriggerModuleDescriptor"/>

Nun kann man den neuen Modultyp anstelle des Standard-Triggers verwenden:

<robust-trigger key="uniqueKey" name="My Trigger" >
    <job key="myJob" />
    <schedule cron-expression="0 0 * * * ?" />
</robust-trigger>

Dabei ist zu beachten, dass in Confluence 2.10 die Definition und die Verwendung des neuen Modultyps nicht in dem selbem Plugin erfolgen dürfen. Das geht erst ab Confluence 3.0.

Artikel als PDF speichern
Eine Antwort zu:
“Workaround für Bug im Trigger Modultyp”
  1. ccf_team
    2. November 2009, 23:48 Uhr

    Workaround für CONF-14828: http://bit.ly/3KkH2B. Ich liebe Reflection
    This comment was originally posted on Twitter

Schreiben Sie einen Kommentar

*

Diese Webseite basiert auf Wordpress. © 2014 Communardo Software GmbH / Kleiststraße 10 a / D-01129 Dresden / Fon +49 (0) 351/8 33 82-0 / info@communardo.de