Startseite > Techblog > Artikel mit dem Tag: plugin
are

Problembeschreibung

Bei der Entwicklung von mehreren Plugins kann es vorkommen, dass Texte mehrfach übersetzt werden müssen, wodurch somit Redundanzen entstehen. Der Ursprung liegt dann bei Atlassian Confluence, welches das Sharen von i18n-keys über die verschiedenen Plugins hinweg nicht ermöglicht.

Beispielhaft soll dies am folgendem Szenario erläutert werden:

Angenommen man hat ein Plugin X entwickelt und in ihm den i18n-key manager.user.email definiert. Zusätzlich existiert ein Plugin Y, dass Plugin X um weitere Funktionalität ergänzt und eine neue vm anlegt, die eben auch den i18n-key manager.user.email verwenden soll. Nun gibt es das Plugin-Konzept von Confluence nicht her auf die in den properties definierten Texte von Plugin X zuzugreifen. Dies bedeutet, dass der Key auch im Plugin Y hinterlegt werden muss. Folglich ergibt sich ein erhöhter Pflegeaufwand.

Info!
Die harte Trennung von Atlassian Confluence ist einleuchtend, da die Plugins untereinander autark funktionieren sollen. Es gibt aber auch Fälle, in denen dies hinderlich ist.

Problemlösung

Info!
Die folgende Erklärung zielt auf die Nutzung eines einzelnen Plugins ab. Es ist natürlich auch möglich für die einzelnen Sprachen separate Plugins (wie Confluence Standard) zu führen.

Damit Redundanzen beseitigt werden können, müssen die i18n-keys zentral abgelegt werden. Dazu kann man einen bestimmten Plugintyp von Confluence – das Sprachplugin – nutzen.

Achtung!
Das Sprachplugin kann mehrere Sprachen repräsentieren. Wichtig ist, dass die in der atlassian-plugin.xml konfigurierten Sprachen (Kombination aus language und country) nur einmal im System auftreten.

Diese Erkenntnis ist wichtig, da für die Lösung des oben genannten Problems, es notwendig ist, die Standard Sprachplugins von Confluence zu deinstallieren und die darin enthaltenen property Dateien in das neue SprachPlugin zu überführen.

Außerdem muss die atlassian-plugin.xml des Sprachplugins, wie folgt angepasst werden.

<language name="German" key="de_DE" language="de" country="DE">

   <resource name="de_DE.png" type="download"
      location="templates/languages/de_DE/de_DE.png">
      <property key="content-type" value="image/png"/>
   </resource>
 </language>

<language name="Spain" key="es_ES" language="es" country="ES">
   <resource name="es_ES.png" type="download"
       location="templates/languages/es_ES/es_ES.png">

       <property key="content-type" value="image/png"/>
   </resource>
</language>

<resource name="i18n" name="i18n_my_plugin" type="i18n" location="/my_plugin"/>

<!-- Important entry, because you have to add the default
          i18n files to this new plugin -->

<resource name="i18n" name="i18n_default" type="i18n"
     location="/ConfluenceActionSupport"/>

Vielseitige Lösung

Diese Lösungsansatz beseitigt nicht nur Redundanzen, sondern bietet auch in Kombination mit Maven, eine Möglichkeit mehrere Varianten einer Pluginlösung textuell abzugrenzen.

Beispielhaft soll dies am folgendem Szenario erläutert werden:
Man stelle sich die Situation vor, es existiert ein Plugin X, welches durch einen eingebauten Schalter unterschiedliche Workflows abdeckt. Möchte man nun innerhalb dieses Plugins in Abhängigkeit des aktuellen Modus andere Texte verwenden, müssen die Keys dupliziert oder die vm-Dateien angepasst werden.

Für diesen Fall kann man mittels Maven tricksen. Wichtig hierbei ist eine eindeutige Namenskonvention für die Unterteilung der properties vorzunehmen. Beispielsweise kann man die properties wie folgt namentlich abgrenzen:

  • my_plugin.properties
  • my_plugin_typex.properties
  • my_plugin_typey.properties
  • my_plugin_de_DE.properties
  • my_plugin_typex_de_DE.properties
  • my_plugin_typey_de_DE.properties

Ist das geschehen, definiert man in der atlassian-plugin.xml des LanguagePool-Plugins folgende Zeilen:

<resource name="i18n" name="i18n_my_plugin_general" type="i18n"
     location="/my_plugin"/>

<resource name="i18n" name="i18n_my_plugin_specific" type="i18n"
     location="/my_plugin_${TYPE}"/>

Letztlich müssen im Eclipse zwei neue Maven Run-Configurations erstellt werden, die das entsprechende Goal (Bsp.: package, install oder atlassian-pdk:install) verwendet und im Environment-Tab die Variable TYPE auf typex oder auf typey setzt.

Kommentar Feed Trackback URL
jsc

Mit einem Webinar (Registrieren) in der Reihe “Plugin of the Month” von Atlassian veröffentlichen wir am 18.2.2010 das Content Import Plugin 1.1.
Das Plugin unterstützt den Import verschiedenster Inhalte nach Confluence. Die Daten müssen in einem Austauschformat, das Confluence Datenstrukturen in XML abbildet, zur Verfügung gestellt werden. Das Austauschformat unterstützt fast alle Inhaltstypen von Confluence (Bereiche, Seiten, Blogeinträge, Kommentare und Anhänge) sowie die zugehörigen Metadaten (Ersteller, Bearbeiter, Schlagworte, Datum). So können ohne vertiefte Confluence Kenntnisse Daten aus verschiedensten Quellsystemen, wie Wikisystemen, Blogs, Foren, nach Confluence importiert werden. Weiterhin bietet Communardo einen Migrationsservice an, der den kompletten Export der Daten aus dem Quellsystem nach XML und den anschließenden Import umfasst.

Migration von Daten nach Confluence mit dem Content Import Plugin

Migration von Daten nach Confluence mit dem Content Import Plugin

Im Webinar (Registrieren) demonstrieren wir das Plugin, weitere Informationen stehen nach dem Release auch auf der Communardo Homepage und im Atlassian Plugin Exchange zur Verfügung.

Kommentar Feed Trackback URL
twi

Auch bei der Pluginentwicklung für Confluence kommt irgendwann der Zeitpunkt, an dem man sich mit komplexeren Abläufen bei der Persistierung von Daten beschäftigen muss. Um die Integrität dieser Daten sicherstellen zu können, ist man dann auf den Einsatz von Transactions angewiesen. Da Confluence das Spring Framework verwendet, bietet sich hierfür die Nutzung des TransactionTemplate an. Dieses ermöglicht es, wie in der Spring Dokumentation beschrieben, auf einfache Weise kritischen Code unter Verwendung eines Callbacks in eine Transaction zu verpacken. Dazu benötigt man jedoch noch einen PlatformTransactionManager. Dieser implementiert die Strategie für die Transaktionsbehandlung, die im Fall von Confluence auf Hibernate basiert. Auch hierzu können weitere Informationen und ein Codebeispiel auf den Seiten von Spring gefunden werden. Der PlatformTransactionManager ist als Bean im Application Context von Confluence vorhanden und kann über den ComponentContainer referenziert werden:

public PlatformTransactionManager getTransactionManager(){
    return (PlatformTransactionManager) ComponentContainer.get("transactionManager");
}

Allerdings funktioniert dieses Codebeispiel nach einer Umstellung auf V2-Plugins nicht mehr. Der Grund: Da diese Plugins in OSGI-Bundles umgewandelt werden, welche eine andere Spring Version verwenden als die Kern-Applikation, kommt es bei der Referenzierung der transactionManager-Bean über den ComponentContainer zu einer ClassCastException.

Bei der Suche nach einer Lösung für dieses Problem bin ich über ein Ticket im Issue Tracker von Atlassian gestolpert, in dessen Kommentaren eine Alternative beschrieben wird: Abhilfe schafft die Verwendung der Shared Access Layer (SAL), einer einheitlichen Service-Schicht für alle Atlassian Anwendungen. Sie stellt neben verschieden anderen Services auch ein TransactionTemplate bereit, das für Confluence bereits den auf Hibernate basierenden PlatformTransactionManager gesetzt hat und auf folgende Weise referenziert werden kann.

Zunächst muss das Template als Komponente (Spring-Bean) im Plugin-Descriptor (atlassian-plugin.xml) importiert werden:

<component-import name="SAL Transaction Template" key="salTransactionTemplate">
    <interface>com.atlassian.sal.api.transaction.TransactionTemplate</interface>
</component-import>

Dann kann man sich die Komponente per Spring Autowiring in fast alle Plugin Modultypen (z. B. Actions und Components ) injizieren lassen. Der Name der zu injizierenden Bean entspricht dem Key des component-import Elementes im Plugin-Descriptor (in diesem Beispiel also “salTransactionTemplate” ):

public void setSalTransactionTemplate(TransactionTemplate template){
    this.transactionTemplate = template;
}

Nun kann das Template wie  oben beschrieben verwendet werden.

Noch ein Hinweis: SAL wird erst ab Confluence 3.0 mit ausgeliefert. Für Confluence 2.10 muss man also eine andere Lösung finden.

&lt;

Kommentar Feed Trackback URL
jsc

Christoph Rauhut von T-Systems Multimedia Solutions gab mit seiner Präsentation zum Confluence Community Day insbesondere für Confluence Neulinge eine Übersicht zu Makros, mit denen Confluence für den Einsatz als Projektwiki optimiert werden kann. Einen Fokus legte er bei der Auswahl der präsentierten Makros auf die Kommunikation, Zusammenarbeit, Aufgabenverwaltung, sowie Inhaltserstellung und -strukturierung im Projekt.
Die Makros demonstrierte Christoph Rauhut live und damit sehr plastisch im Wiki für ein gedachtes „Projekt“ Confluence Community Day. Die Vortragsdokumentation enthält Screenshots der Macros in Aktion und den zugehörigen Macroaufruf.
Artikel vollständig lesen »

Kommentar Feed Trackback URL
twi

Communardo is submitting a Confluence plugin to this years Codegeist competition, powerded by Atlassian.

The Notify&Tag Plugin adds twitter-like functionality to Confluence. It allows to add labels to pages and news by using #hashtags. Additionally users can be notified about interesting content (pages, news and comments) by using the @username notation.

To create a label from a term in the content of a page or news item just precede  it with “#” while writing the text. There is no need to provide it again in the according form field: Press “Save” and it will be added to the list of labels.

To notify a user about the page, news or comment you are creating, simply add his username to the text and put “@” in front of it. After saving he will recieve an email containing an excerpt and a link to content. This is a nice feature to attract the attention to relevant information, like the minutes of a missed meeting. You are not requiring to track the activity of the whole site using RSS feeds or the recently-updated macro. Thus, the danger of missing important information is reduced (provided emails are checked on a regular basis ;) ).

The presentation below gives some additional information. For more exhaustive usage dokumentation you can visit the plugin homepage.

Needless to say, we are eager to get your feedback. So feel free to add a comment to this blog or any of the plugin pages and tell us about your opinion or the feature you are missing.

Kommentar Feed Trackback URL
twi

Die Confluence API bietet über das Bandana-Framework eine einfache Möglichkeit zum Speichern beliebiger Java Objekte an. Im Prinzip muss man zu dem Objekt nur einen einen Kontext (bezieht sich auf einen bestimmten Confluence Space oder ist global) und einen bezüglich dieses Kontextes eindeutigen Key angeben und der BandanaManager kümmert sich um den Rest. Der Vorteil liegt auf der Hand: Man muss sich nicht mit dem Persistenzmodell von Confluence (basiert auf Hibernate) auseinander setzen. Davon rät Atlassian ohnehin ab, Zitat:

Unless you really understand our code, something weird will happen.

Das Speichern von Daten über Bandana geschieht im Wesentlichen in zwei Schritten

  1. Serialisierung der zu persistierenden Objekte mittels XStream
  2. Ablegen des Resultates in der Datenbank

Diese Form der Persistenz hat allerdings auch ihre Tücken. Als ich vor Kurzem bei der Entwicklung eines Plugins mal wieder Bandana verwendete bin ich über das folgende Verhalten gestolpert:

Ich hatte zwei Container-Datenstrukturen gespeichert, eine Map und eine List. Nachdem einige kurze Tests positiv verliefen, wendete ich mich einer anderen Komponente des Plugins zu. Um diese zu testen baute ich mein Plugin neu und installierte es über die Weboberfläche (ohne etwas an meiner “Persistenzschicht” zu ändern). Allerdings musste ich nun feststellen, dass eine der Datenstrukturen (die Map) nicht mehr geladen werden konnte.  Ein weiterer Test offenbahrte noch wunderlicheres Verhalten: Nachdem ich die Map erneut gespeichert hatte, konnte ich sie wieder auslesen, allerdings nur bis zum nächsten Deploy des Plugins.

Was war passiert? An einem falschen Kontext oder Key konnte es nicht liegen, da diese bereits zuvor das Laden der Map verhindert hätten. Der Verdacht viel schnell auf irgendeinen Cache. Und tatsächlich, nach kurzer Recherche bin ich auf diese Seite bei Atlassian gestoßen. Dort wird beschrieben, dass es eigens für Bandana einen Cache gibt. Meine erste Vermutung war nun, dass die Map aus irgend einem Grund nie den Weg durch den Cache in die Datenbank geschafft hatte, der dann bei der Neuinstallation des Plugins verfiehl. Ein kurzer Blick in die Datenbank und ein wenig Debugging überzeugten mich dann aber vom Gegenteil: Die Daten waren in der Datenbank, schafften es von da aber nicht mehr in den Cache (kurzer Hinweis: die Tabelle für die Bandana-Daten heißt treffender Weise BANDANA). Nach weiterem Debugging stand fest, dass die Daten zwar noch aus der Datenbank geholt wurden, im Anschluss aber die Deserialisierung fehl schlug. Nach einem erneuten Blick in die Datenbank war schnell klar warum. Ich hatte Enums als Schlüssel für die Map verwendet. Diese waren fehlerhaft serialisiert wurden, so dass sie (und mit ihnen die Map) nicht wiederhergestellt werden konnten. Das liegt wohl daran, dass Confluence die XStream Version 1.1.1 verwendet aber Enums erst mit der Version 1.1.2 unterstützt werden. Da die Daten im Cache immer unserialisiert gespeichert werden, fiel dieses Problem erst auf, als der Cache verfallen war. Die Lösung war nun recht einfach: Nach dem Ersetzen der Enums durch Strings verhielt sich mein Plugin wie erwartet.

Enums sind nicht die einzigen Datenstrukturen, mit denen es Probleme gibt. So sollte man es auch vermeiden in einem Plugin definierte Typen mittels Bandana zu speichern, wenn diese keinen Default-Konstruktor haben. Der Grund: Diese Typen würden, wie in diesem Issue beschrieben, beim Deserialisieren mit dem ClassLoader der Web-Applikation gesucht werden. Der kann sie aber nur finden, wenn sie im Classpath der der Web-Applikation liegen, was bei über die Weboberfläche installierten Plugins nicht der Fall ist (dafür hat jedes Plugin seinen eigenen ClassLoader). Also dürften in diesem Fall ebenfalls die oben beschriebenen Probleme auftreten.

Kommentar Feed Trackback URL
jsc

Häufig habe ich schon erlebt, dass Nutzer nach der Einführung von Confluence die Dokumentation bei Atlassian lesen, dabei viele neue Plugins entdecken und um die Installation der Plugins bitten. Administratoren sind dann oftmals unsicher, nach welchen Gesichtspunkten über die Installation der Plugins entschieden werden soll.
Auf der einen Seite erweitern Plugins die Funktionalität von Confluence und können damit die Benutzerakzeptanz steigern und eine effizientere Arbeit mit dem Wiki erlauben. Auf der anderen Seite können Plugins die Stabilität, Sicherheit und Performance eines Confluence-Systems entschieden beeinträchtigen. Mit Hilfe von Plugins können alle Teile des Wikis und sogar die Datenbank verändert werden.

Wie soll da über die Installation eines Plugins entschieden werden?

Die folgende Checkliste, unterteilt in Fragen zur fachlichen und zur technischen Bewertung, will Anhaltspunkte geben – wenn auch in die letztendliche Entscheidung über die Installation eine Plugins die Erfahrung des Administrators oder vielleicht das Knowhow eines Confluence-Consultants einfließen.

Fragen zur fachlichen Bewertung:

  • Wird das Plugin wirklich benötigt um das bestehende Wiki zu verbessern?
    So ist möglicherweise das Sudoko-Plugin nicht unbedingt geeignet um ein Wissensmanagementsystem zu verbessern, dagegen können mit Hilfe des Rate-Macros die Wissensinhalte bewertet werden und damit den Nutzern erweiterte Information zur Einordnung des Inhalts zur Verfügung gestellt werden.
  • Wird die Funktionalität des Plugins bereits durch Standardfunktionalität von Confluence oder durch andere bereits installierte Plugins abgebildet?
    Das Excel-Plugin erlaubt beispielsweise die Inhalte von an Wikiseiten gehängten Excel-Dokumenten anzuzeigen – diese Funktionalität und weitere Features zum Anzeigen und Bearbeiten von Office-Dokumenten werden jedoch auch (tw. in verbesserter Form) durch den mitgelieferten Office Connector zur Verfügung gestellt.
  • Soll mit dem Plugin Funktionalität ins Wiki gebracht werden, für die andere Systeme vorhanden und besser geeignet sind?
    Das Calendar-Plugin erlaubt zum Beispiel eine Terminverwaltung, dennoch ist für die persönliche Terminverwaltung sicherlich bessere Software als ein Wiki denkbar. Das Metadata-Plugin und Metadata-Plugin 2 hingegen bringen semantische Funktionalitäten ins Confluence (auf Wikiseiten können beispielsweise semantische Informationen hinterlegt werden, die auf anderen Wikiseiten ausgewertet werden können) und erweiteren damit die Kernfunktionalität des Wikis.

Fragen zur technischen Bewertung:

  • Ist das Plugin zu meiner Confluence-Version kompatibel?
    Dies ist eigentlich die wichtigste Frage für die technische Bewertung eines Plugins. Die Informationen sind meist auf der Homepage des Plugins verfügbar. Wenn das Plugin nicht zur Confluenceversion kompatibel ist oder die Kompatibilitätsinformationen fehlen, sollte auf die Installation verzichtet werden.
  • Was hat die Installation und Nutzung des Plugins auf dem Testsystem ergeben?
    Vor der Installation auf dem Produktivsystem sollten Plugins immer auf einem Testsystem installiert und getestet werden. Dabei zeigen sich häufig schon eventuelle Probleme bei der Verwendung des Plugins. Plugins, die unsauberen HTML-Code ausliefern, können beispielsweise das Layout einer Seite kaputtmachen. Außerdem gibt es Macros, die für eine sehr lange Ladezeit ihrer Seiten sorgen usw. Auch auf die Ausgabe eventueller Fehlermeldung in den Logfiles sollte geachtet werden.
  • Wird das Plugin von Atlassian supportet?
    Plugins, die von Atlassian supportet werden, haben eine gewisse Qualitätskontrolle bestanden und Atlassian hilft im Falle von Problemen mit dem Plugin weiter. Die fehlende Unterstützung durch den Atlassian Support sollte jedoch kein alleiniger Grund sein, die Installation abzulehnen.
  • Wer hat das Plugin zur Verfügung gestellt?
    Plugins, die von Atlassian, renomierten Atlassian Partnern wie Adaptavist oder Customware, oder Communardo zur Verfügung gestellt werden, sind vertrauenswürdiger als die erste Version des ersten Plugins eines einzelnen Entwicklers.
  • Haben andere Nutzer Erfahrungen mit dem Plugin und wie bewerten sie das Plugin?
    Diese Informationen finden sich meist in den Kommentaren auf der Homepage des Plugins, manchmal geben auch die Entwickler des Plugins selbst Hinweise zur Einsatzfähigkeit des Plugins.
  • Wie ist die Performace des Plugins?
    Häufig werden Plugins für kleinere oder mittlere Confluence-Systeme entwickelt und die besonderen Herausforderungen eines großen oder gar geclusterten Systems werden nicht beachtet. Eine endgültige Aussage über die Performance eines Plugins können nur Lasttests liefern.
  • Ist die Installatio über das Plugin Repository möglich?
    Plugins, die über das Plugin-Repository installiert werden können (und nicht per Kopieren von Dateien in den Ordner “WEB-INF/lib”) erlauben einfacheres Warten und Updaten des Plugins.

Fazit: Bei der Entscheidung zur Installation eines Plugins gilt der allgemeine Leitsatz
“So viel nötig, so wenig wie möglich” auch!

(das Nennen von Plugins in diesem Artikel enthält keinerlei Bewertung für die Auswahl des Plugins. Die genannten Plugins dienen nur als Beispiele, die die Fragen der Checkliste verdeutlichen sollen)

Kommentar Feed Trackback URL
she

Bei der Entwicklung von Confluence Plugins kommt häufig die auf Java basierende Buildmanagement-Software Maven zum Einsatz. Ziel dabei ist es, die Entwickler vom Anlegen des Projektes bis hin zum Kompilieren und Testen zu unterstützen und möglichst viele Schritte des Softwaremanagements automatisiert ablaufen zu lassen. Ein Tutorial für die Entwicklung von Confluence Plugins mit Hilfe von Maven findet sich auf den Seiten der Confluence Community.

Wenn eine solche Entwicklungsumgebung eingerichtet wurde, kann der Buildprozess eines Plugins noch weiter vereinfacht werden. Dafür stellt Atlassian das Plugin Developer Kit for Maven2 (kurz PDK) zur Verfügung. Dabei handelt es sich um ein Maven-Plugin, welches einfach in der POM des eigenen Projektes eingebunden werden muss und dann automatisch beim Buildprozess heruntergeladen und installiert wird. Ein solcher Aufruf kann z.B. so aussehen:

<plugin>
   <groupId>com.atlassian.maven.plugins</groupId>
   <artifactId>atlassian-pdk</artifactId>
   <executions>
      <execution>
         <phase>package</phase>
         <goals>
            <goal>uninstall</goal>
            <goal>install</goal>
            <goal>rescan</goal>
         </goals>
      </execution>
   </executions>
</plugin>

Dabei können verschiedene Goals angegeben werden, welche hintereinander ausgeführt werden und z.B. das Plugin direkt nach dem kompilieren in einem laufenden Confluence deinstallieren und die neue Version installieren. Eine sinnvolle Reihenfolge wäre z.B. UninstallInstallRescan.

Vorsicht ist allerdings bei der Benutzung des Confluence Trigger Plugin Moduls geboten. Hat man einen Trigger in seiner atlassian-config.xml eingebunden und installiert das Plugin über das PDK direkt in ein laufendes Confluence, sollte nach einem Install kein explizites Enable des Plugins ausgeführt werden. Der Grund dafür ist: der Job wird bereits beim Install angelegt. Bei einem folgenden Enable wird dann erneut versucht, dieser Job anzulegen – was natürlich fehlschlägt und mit einer ObjectAlreadyExistsException quittiert wird. Ein Install und ggf. Rescan ist in diesem Fall also ausreichend.

Kommentar Feed Trackback URL

Tag Cloud

Unsere Themen

Kommentare

  • SharePoint_Team: Rückblick zum Treffen der .NET Usergroup Dresden am 24.02.2010: im #Communardo #Techblog...
  • TorstenHu: Rückblick zum Treffen der .NET Usergroup Dresden am 24.02.2010: im #Communardo #Techblog...
  • SharePoint_Team: Neuer Blogpost zur #BastaCon im #Communardo #TechBlog: http://tinyurl.com/yjqyqpb This comment was...
  • SharePoint_Team: Nur noch etwa 1 Stunde, dann beginnt die .NET Usergroup… http://bit.ly/dxDoKg This comment was...
  • SharePoint_Team: RT @TorstenHu: ViS is waiting for an operation oder Warum Copy & Paste schlecht ist: #Communardo...

Twitter