Communardo Software GmbH, Kleiststraße 10 a, D-01129 Dresden
0800 1 255 255

Workaround für Bug im Trigger Modultyp

Seit Confluence 2.10 gibt es einen ziem­lich unan­ge­neh­men Bug im Trigger-Plugin-Modultyp:

Manchmal kommt es vor, dass ein Plugin bei der Installation nicht erfolg­reich akti­viert wer­den kann. In die­sem Fall wer­den alle Module deak­ti­viert, also auch der Trigger. Dabei wird aber auch ver­sucht den zuge­hö­ri­gen Job zu deak­ti­vie­ren. Ist der zu dem Zeitpunkt noch nicht voll­stän­dig gela­den, kommt es zu einer IllegalStateException. In der Folge befin­det sich das Plugin in einer Art "Zwischenzustand". Es erscheint zwar als instal­liert und akti­viert in der Pluginübersicht, aber keine der vom Plugin bereit­ge­stellt Funktionen sind ver­füg­bar. Außerdem kann das Plugin erst nach einem Neustart von Confluence aus dem System ent­fernt wer­den. Jeder Versuch es ohne Neustart zu deinstal­lie­ren wird mit einer org.springframework.orm.ObjectRetrievalFailureException quittiert.

Da die­ses Problem die Wartung von Kundeninstallationen und Nightly Builds erheb­lich erschwert, musste ein Workaround her. Da es seit Confluence 2.10 die Möglichkeit gibt eigene Plugin Modultypen zu defi­nie­ren indem man den neuen Module-Type-Modultyp ver­wen­det, war es rela­tiv ein­fach eine Lösung zu fin­den, die sogar als Plugin instal­liert wer­den kann (keine Anpassung des Confluence Kerns nötig!): Man defi­niert einen Modultyp, der von TriggerModuleDescriptor (der Implemetation des Trigger-Plugin-Modultyps) erbt. Dort über­schreibt man die Methode dis­ab­led(), 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 über­schrie­ben um die vom Trigger benö­tigte Scheduler-Bean zu inji­zie­ren. Im TriggerModuleDescriptor wird diese Bean durch Autowiring auto­ma­tisch gesetzt. Da der abge­lei­tete RobustTriggerModuleDescriptor aber ein ande­rer Modultyp ist, fin­det bei des­sen Initialisierung kein Autowiring statt.

Um den neuen Modultyp nut­zen zu kön­nen, 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 beach­ten, dass in Confluence 2.10 die Definition und die Verwendung des neuen Modultyps nicht in dem sel­bem Plugin erfol­gen dür­fen. Das geht erst ab Confluence 3.0.

Related Posts

1 Kommentar

Workaround für CONF-14828: http://bit.ly/3KkH2B. Ich liebe Reflection
This com­ment was ori­gi­nally pos­ted on Twitter

Comments are closed.

Pin It on Pinterest