Entwicklung eines JIRA Gadgets Ein generisches Balkendiagramm

Transcrição

Entwicklung eines JIRA Gadgets Ein generisches Balkendiagramm
Entwicklung eines JIRA Gadgets
Ein generisches
Balkendiagramm
15.09.2011, Atlassian User Group
Leo von Klenze, Alexander Arth
1
Motivation
JIRA Überblick
JIRA für das Beschwerdemanagement
Auswertungen mit JIRA
2
Entwicklung von Gadgets
3
Komponenten eines JIRA Gadgets
Definition des Plugins: atlassian-plugin.xml
Definition des Gadgets: gadget.xml
Nutzen der REST API
4
Testen des Plugins und Validierung
Automatisierte Tests
Validierung von Benutzereingaben
5
Das fertige Balkendiagramm Plugin
6
Zum Schluss
Motivation
Motivation
JIRA Überblick
Motivation
JIRA Überblick
�
Bugtracker von Atlassian (http://www.atlassian.com/JIRA)
�
�
Einfach zu bedienen (für den Benutzer)
�
Umfangreich zu konfigurieren (seit 4.4 etwas übersichtlicher �)
Motivation
JIRA für das Beschwerdemanagement
�
Eigener Workflow
�
Eigene Felder (Eigenschaften eines Tickets)
�
Verwendung im Fachbereich
�
Auswertungen notwendig
In diesem Fall über Eingangsmonat und Herkunft
Motivation
Auswertungen mit JIRA
�
Auswertungen basieren auf Filtern
Auswahl von Tickets mit bestimmten Eigenschaften
�
Verschiedene visuelle Darstellungen von Filtern möglich
Motivation
Auswertungen mit JIRA
�
Auswertungen basieren auf Filtern
Auswahl von Tickets mit bestimmten Eigenschaften
�
Verschiedene visuelle Darstellungen von Filtern möglich
Motivation
Auswertungen mit JIRA
�
Auswertungen basieren auf Filtern
Auswahl von Tickets mit bestimmten Eigenschaften
�
Verschiedene visuelle Darstellungen von Filtern möglich
Motivation
Ziel der Auswertung
Motivation
Ziel der Auswertung
Motivation
Berichte vs. Gadgets
�
Es gibt in JIRA sogenannte Berichte zur Auswertung
�
Allerdings nur wenige vordefinierte Berichte
�
Konfiguration muss jedesmal neu ausgewählt werden (Filter/Typ)
�
Gute Druckansicht
Motivation
Berichte vs. Gadgets
�
Gadgets sind sofort auf der Startseite sichtbar
�
Pro Startseite sind mehrere Gadgets möglich
�
Gadgets merken sich ihre Konfiguration
�
Zur Zeit keine gute “out-of-the-box”-Druckansicht
Motivation
Auswertungen mit Gadgets
�
Knapp 30 vordefinierte Gadgets
�
Nur wenige Gadgets, die Auswertungen auf eigenen Feldern ermöglichen
�
Problem: oft an spezielle JIRA-Felder gebunden, z.B. “Erstellt vs. Erledigt”
�
In diesem Fall benötigt: gestapeltes Balkendiagramm (Monat, Herkunft)
Lösung: eigenes Gadget entwickeln �
Entwicklung von Gadgets
Entwicklung von Gadgets
Allgemeine Vorteile von Gadgets
�
Sofortige Präsenz auf Startseite
�
Anpassbarkeit
�
Interaktivität
�
Cross Plattform Einsetzbarkeit (⇒ Open Social Api)
Entwicklung von Gadgets
Tools, Techniken und Sprachen
�
Build Tools (Maven)
�
Konfiguration: XML
�
Frontend: HTML, CSS
�
Backend: JavaScript, AJAX, Java
Komponenten eines JIRA Gadgets
Komponenten eines JIRA Gadgets
atlassian-plugin.xml
�
Plugin Beschreibung
�
Definition von Plugin Komponenten
Komponenten eines JIRA Gadgets
atlassian-plugin.xml
�
Plugin Beschreibung
�
Definition von Plugin Komponenten
<g a d g e t key=” b a r c h a r t ” l o c a t i o n= ”com/ t n g t e c h / j i r a / p l u g i n s /
g a d g e t / b a r c h a r t −g a d g e t . xml ” />
< r e s t key=” r e s t −r e s o u r c e s ” p at h=” / j i r a −r e s t ” v e r s i o n=” 1 . 0 ”>
< d e s c r i p t i o n> S t e l l t d i e nö t i g e n REST R e s o u r c e n f ü r d a s
Gadget b e r e i t</ d e s c r i p t i o n>
</ r e s t>
Komponenten eines JIRA Gadgets
Aufbau der gadget.xml
�
Allgemeine Beschreibung des Gadgets
�
Benötigte Module
�
User Authentifizierung
�
Einstellungsvariablen
�
HTML und JavaScript Code für zwei Ansichten
–
Konfiguration → Descriptor
–
Ergebnisansicht → View
Komponenten eines JIRA Gadgets
Aufbau der gadget.xml
�
Allgemeine Beschreibung des Gadgets
�
Benötigte Module
�
User Authentifizierung
�
Einstellungsvariablen
�
HTML und JavaScript Code für zwei Ansichten
–
Konfiguration → Descriptor
–
Ergebnisansicht → View
⇒ Funktionierendes Beispiel aus Vorlage ist sinnvoll. Tutorials von Atlassian
funktionieren nicht mehr richtig mit aktuellen Versionen!
Komponenten eines JIRA Gadgets
Aufbau der gadget.xml [1]
<Module>
<M o d u l e P r e f s t i t l e =” B a l k e n d i a g r a m m ” a u t h o r=”TNG”
d e s c r i p t i o n=” E i n g e n e r i s c h e s B a l k e n d i a g r a m m . ”>
<R e q u i r e f e a t u r e=” o a u t h p o p u p ” />
....
#o a u t h
</ M o d u l e P r e f s>
<U s e r P r e f name=” i s C o n f i g u r e d ” d a t a t y p e=” h i d d e n ”
d e f a u l t v a l u e=” f a l s e ” />
....
<Content t y p e=” h t m l ”><! [CDATA[
#r e q u i r e R e s o u r c e ( ” com . a t l a s s i a n . g a d g e t s . p u b l i s h e r : a j s −
gadgets ”)
....
#i n c l u d e R e s o u r c e s ( )
Komponenten eines JIRA Gadgets
Aufbau der gadget.xml [2]
< s c r i p t t y p e=” t e x t / j a v a s c r i p t ”>
( function () {
v a r g a d g e t = AJS . Gadget ( {
b a s e U r l : ” ATLASSIAN BASE URL ” ,
u se Oa ut h : ”/ r e s t / g a d g e t / 1 . 0 / c u r r e n t U s e r ” ,
config : { descriptor : function ( args ) { . . . . } } ,
view : { template : function ( args ) { . . . . } }
}) ;
}) ( ) ;
</ s c r i p t >
]] >
</Content>
</Module>
Komponenten eines JIRA Gadgets
Gadgetkonfiguration: descriptor [1]
descriptor : function ( args ) {
v a r p r o j e c t O r F i l t e r P i c k e r = AJS . t h i s . f i e l d s .
projectOrFilterPicker ( this , ” p r oj ect O r F ilt e r Id ” , args .
options ) ;
return { f i e l d s : [
projectOrFilterPicker ,
{
userpref : ” axisField ”,
l a b e l : ” x−Achse : ” ,
d e s c r i p t i o n : ” F e l d f ü r Werte d e r x−Achse . ” ,
type : ” s e l e c t ” ,
s e l e c t e d : t h i s . g e t P r e f (” a x i s F i e l d ”) ,
options : args . a x i s F i e l d . fieldNames
},
AJS . t h i s . f i e l d s . n o w C o n f i g u r e d ( )
] };
},
....
Komponenten eines JIRA Gadgets
Gadgetkonfiguration: Möglichkeiten
�
Vorgefertigte Konfigurationsfelder, z.B. projectOrFilterPicker
�
Selbstgebaute Optionen aus Standardtypen, z.B. type=“select“
Komponenten eines JIRA Gadgets
Gadgetkonfiguration: Möglichkeiten
�
Vorgefertigte Konfigurationsfelder, z.B. projectOrFilterPicker
�
Selbstgebaute Optionen aus Standardtypen, z.B. type=“select“
Vor- und Nachteile
�
Es gibt keine Seite mit allen Möglichkeiten
�
Einheitliche Namensgebung ermöglicht erfolgreiches Raten,
z.B. filterPicker oder type=“text“
Komponenten eines JIRA Gadgets
Gadgetkonfiguration: Möglichkeiten
�
Vorgefertigte Konfigurationsfelder, z.B. projectOrFilterPicker
�
Selbstgebaute Optionen aus Standardtypen, z.B. type=“select“
Vor- und Nachteile
�
Es gibt keine Seite mit allen Möglichkeiten
�
Einheitliche Namensgebung ermöglicht erfolgreiches Raten,
z.B. filterPicker oder type=“text“
�
Erzeugter HTML Code nicht perfekt → Checkbox geht im IE nicht!
Komponenten eines JIRA Gadgets
Gadgetkonfiguration: descriptor [2]
descriptor : function ( args ) {
....
,
args : [{
key : ” a x i s F i e l d ” ,
ajaxOptions : function () {
return {
u r l : ”/ r e s t / j i r a −r e s t / 1 . 0 / B a r C h a r t C o n f i g u r a t i o n /
LookupCustomFields ”
};
}
}]
}
Komponenten eines JIRA Gadgets
Gadgetkonfiguration: descriptor [2]
descriptor : function ( args ) {
....
,
args : [{
key : ” a x i s F i e l d ” ,
ajaxOptions : function () {
return {
u r l : ”/ r e s t / j i r a −r e s t / 1 . 0 / B a r C h a r t C o n f i g u r a t i o n /
LookupCustomFields ”
};
}
}]
}
View wird analog definiert und modifiziert DOM direkt
Komponenten eines JIRA Gadgets
Java-REST-Klasse
@Path ( ” / B a r C h a r t C o n f i g u r a t i o n ” )
@ P r o d u c e s ( { MediaType . APPLICATION JSON } )
public class BarChartGadgetConfiguration {
public BarChartGadgetConfiguration (
J i r a A u t h e n t i c a t i o n C o n t e x t jAC , . . . . ) { . . . . }
@GET
@Path ( ” / L o o k u p C u s t o m F i e l d s ” )
p u b l i c Response lookupCustomFieldNames ( ) {
try {
F i e l d L i s t f i e l d L i s t = getFieldList () ;
r e t u r n R e s p o n s e . ok ( f i e l d L i s t ) . b u i l d ( ) ;
}
catch ( RuntimeException e ) {
r e t u r n Response . s e r v e r E r r o r ( ) . b u i l d ( ) ;
}
}
....
}
Komponenten eines JIRA Gadgets
FieldList-Klasse
�
Objekt in Response beliebig
Komponenten eines JIRA Gadgets
FieldList-Klasse
�
Objekt in Response beliebig
�
Muss aber in Klassendefinition annotiert sein!
�
⇒ Einfache Response Objekte wie Response.ok(”Hello World”) funktionieren
nicht!
Komponenten eines JIRA Gadgets
FieldList-Klasse
�
Objekt in Response beliebig
�
Muss aber in Klassendefinition annotiert sein!
�
⇒ Einfache Response Objekte wie Response.ok(”Hello World”) funktionieren
nicht!
@XmlRootElement
public class FieldList {
@XmlElement
p u b l i c L i s t <Map<S t r i n g , S t r i n g >> f i e l d N a m e s ;
p u b l i c F i e l d L i s t (Map<Long , S t r i n g > f i e l d I n f o s ) {
// f i e l d N a m e s b e f ü l l e n
}
}
Komponenten eines JIRA Gadgets
Stolpersteine im Java Code
�
Exceptions im Java Code
⇒ Try Catch um Rest Aufruf und Response.serverError()
Komponenten eines JIRA Gadgets
Stolpersteine im Java Code
�
Exceptions im Java Code
⇒ Try Catch um Rest Aufruf und Response.serverError()
�
Rest Klassen werden als Singleton instanziiert
⇒ Threadsafe programmieren! (ThreadLocal)
Komponenten eines JIRA Gadgets
Stolpersteine im Java Code
�
Exceptions im Java Code
⇒ Try Catch um Rest Aufruf und Response.serverError()
�
Rest Klassen werden als Singleton instanziiert
⇒ Threadsafe programmieren! (ThreadLocal)
�
Standardeinstellung bzgl. Caching der REST Aufrufe varriiert
⇒ new CacheControl().setNoCache(true) an Response anhängen
Testen des Plugins und Validierung
Testen des Plugins und Validierung
Unit- und Integrationstests
�
Testing Framework: JUnit
�
Mocking Framework: Mockito
�
Momentan 88 Unit Tests und 1 Integrations Test (Stand 15.9.)
�
Automatisiertes Laden der Testdaten für manuelles Testen der GUI
Testen des Plugins und Validierung
Wieso nur 1 Integrationstest?
�
Code Design: Code Coverage durch Unit Tests ca 71%
�
JIRA API bietet FuncTestCase Klasse als GUI Tester
�
Problem: Gadgets liegen in iFrames ⇒ DOM versteckt
Testen des Plugins und Validierung
Wieso nur 1 Integrationstest?
�
Code Design: Code Coverage durch Unit Tests ca 71%
�
JIRA API bietet FuncTestCase Klasse als GUI Tester
�
Problem: Gadgets liegen in iFrames ⇒ DOM versteckt
�
Mocken der kompletten JIRA-API komplex, aber möglich
⇒ Erstellen einer Klasse JiraUtils, die durchgereicht wird und als einzige
Schnittstelle zur Jira API dient
Testen des Plugins und Validierung
Validierung von Benutzereingaben
Javascript:
�
Validierung von Texteingaben
Testen des Plugins und Validierung
Validierung von Benutzereingaben
Javascript:
�
Validierung von Texteingaben
Java:
�
Setzen einer Flag, wenn die Konfiguration geändert wird
�
Weitergeben von Flag und User Input an Java-Klasse
�
Validierung z.B. ob gewähltes Custom Field korrekt unterstützt wird
�
Behandlung der Ergebnisse über window.alert()
Das fertige Balkendiagramm Plugin
Das fertige Balkendiagramm Plugin
Konfiguration
Das fertige Balkendiagramm Plugin
Das Balkendiagramm
Zum Schluss
Hinweise
�
Atlassian JIRA: http://www.atlassian.com/software/jira/
�
Dashboard einrichten: http://confluence.atlassian.com/display/
JIRA/Customising+the+Dashboard
�
JIRA Developer Documentation (Atlassian SDK, Plugin Guide, . . . )
http://confluence.atlassian.com/display/JIRADEV/JIRA+
Developer+Documentation
�
Das Plugin wird gerade im Atlassian-Plugin-Exchange veröffentlicht
Vielen Dank für die Aufmerksamkeit!

Documentos relacionados