Gestylte Checkboxen und Radio-Buttons mit Angular

Das Aussehen von Formularelementen wie Checkboxen, Radio-Buttons oder Dropdowns lassen sich nicht so einfach verändern wie das von anderen HTML-Elementen. Es gibt diverse JavaScript-Bibliotheken die Abhilfe bieten, oft entstehen dadurch aber neue Probleme:

  • die Elemente sind nicht mehr tastaturbedienbar und somit ist die Webseite nicht mehr barrierefrei
  • auf gewissen Geräten (z.B. auf Touch-Devices) treten Bugs auf
  • integriert sich schlecht in andere JavaScript-Frameworks wie z.B. ein Data-Binding mit Angular

Es gibt diverse Ansätze, Checkboxen und Radio-Buttons nur mit CSS (also ohne JavaScript) zu stylen. Am Beispiel von Roger Johansson’s Vorschlag  zeige ich nachfolgend, wie sich das mit Angular kombinieren lässt.

Der Ansatz macht sich zu Nutze, dass die Interaktion mit einem <label>-Element an das verbundene Input-Feld delegiert wird. Klickt der Benutzer auf das Label einer Checkbox wird diese angehakt.

Für das Styling ist zusätzliches Markup nötig

  • ein Element, um das Bild der Checkbox anzuzeigen
  • ein Wrapper, der das Bild und das Input-Feld umgibt
<span class="wrapper">
    <input type="checkbox"/>
    <i class="icon"></i>
</span>

Dieses Markup erzeugen wir mit einer Angular-Direktive:

app.directive("styledinput", function() {
    return {
        restrict: 'A',
        link: function (scope, elem, attrs) {
            elem.wrap('<span class="styledinput-wrapper"></span>');
            elem.after('<i></i>');
        }
    };
});

Vorteile:

  • im Template selber schreiben wir nur das semantisch relevante Markup
    <input type="checkbox" styledinput />
  • benötigen wir später mal eine andere Markup-Struktur müssen wir dies nur in der Direktive anpassen, nicht an allen verwendeten Stellen.

Erweiterungen

Obige Lösung geht davon aus, dass die Input-Felder immer innerhalb eines Label-Tags verwendet werden.

<label><input type="checkbox" styledinput /> Bedinungen akzeptieren</label>

Die Direktive kann einfach erweitert werden, um auch mit Markup umgehen zu können, das sich nicht an diese Konvention hält. Z.B. so

link: function (scope, elem, attrs) {
    var parentTag = elem.parent()[0].tagName.toLowerCase();
    var wrapperTag = 'label';
    if (parentTag === 'label') {
        wrapperTag = 'span';
    }
    elem.wrap('<' + wrapperTag + ' class="styledinput-wrapper"></' + wrapperTag + '>');
      elem.after('<i></i>');
}

Beispielcode

Wie all das zusammenspielt ist in https://jsfiddle.net/stefani_gerber/8mpz1asL/ zu sehen.

Selenium WebDriver

Einführung

Selenium WebDriver ist der Nachfolger von Selenium RC (siehe auch Blogbeitrag zu Selenium RC) und entstand aus dem Zusammenschluss vom Selenium-Projekt mit WebDriver. Es wurde im Juli 2011 released. Wie sein Vorgänger wird Selenium WebDriver verwendet, um automatisierte Tests zu programmieren.

Wie funktioniert Selenium WebDriver?

Im Gegensatz zu Selenium RC verwendet es kein JavaScript mehr um den Browser zu steuern sondern tut dies direkt über das Automation API des jeweiligen Browsers. Somit ist das Verhalten näher an dem eines echten Benutzers. Der Selenium Server wird durch die Verwendung des Automation API überflüssig.

Der Browser wird über einen jeweiligen Driver angesprochen, z.B. ChromeDriver oder PhantomJSDriver.

Beispiel eines Testskripts

Um beim selben Beispiel zu bleiben wie bei den beiden vorderen Blogeinträgen nachfolgend der Code, der beim Exportieren aus Selenium IDE entsteht (nicht verwendete Methoden wurden bereits entfernt).

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

import java.util.concurrent.TimeUnit;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;

public class SampleTestCase {
  private WebDriver driver;
  private String baseUrl;
  private StringBuffer verificationErrors = new StringBuffer();

  @Before
  public void setUp() throws Exception {
    driver = new FirefoxDriver();
    baseUrl = "https://www.google.ch/";
    driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
  }

  @Test
  public void testSampleTestCase() throws Exception {
    driver.get(baseUrl + "/?gws_rd=ssl");
    driver.findElement(By.id("lst-ib")).clear();
    driver.findElement(By.id("lst-ib")).sendKeys("Bluesky");
    driver.findElement(By.name("btnG")).click();
    driver.findElement(By.linkText("Bluesky IT-Solutions AG")).click();
    try {
      assertEquals("DIGITAL PRESENCE", driver.findElement(By.xpath("//div[@id='menu']/ul/li[2]/a/div/div")).getText());
    } catch (Error e) {
      verificationErrors.append(e.toString());
    }
  }

  @After
  public void tearDown() throws Exception {
    driver.quit();
    String verificationErrorString = verificationErrors.toString();
    if (!"".equals(verificationErrorString)) {
      fail(verificationErrorString);
    }
  }
}

Die Abfolge der Befehle unterscheidet sich nicht gross von Selenium RC. Sie werden auf einer WebDriver-Instanz (Interface zu Browser) ausgeführt anstatt auf einer Selenium-Instanz (Interface zu Selenium-Server). Was jedoch entfällt sind die expliziten waits; Methoden wie z.B. findElement überprüfen stattdessen die Seite wiederholend auf ein Element bis sie dieses entweder finden, oder ein Timeout erreicht wird. Das erleichtert z.B. das Testen von Webseiten mit Ajax-Calls, wo nur Seitenteile nachgeladen werden. Das implizite Timeout kann auf der WebDriver-Instanz gesetzt werden und wenn nötig auch für gewisse Testabschnitte hoch- oder runtergesetzt werden.

Gleich wie bei Selenium RC ist es auch hier wichtig, robuste Selektoren zu wählen.

Ausblick

Geplant ist, mit Selenium 3 vermehrt mobile Browser und Web-Applikationen abzudecken. Die Roadmap hierzu wurde allerdings seit August 2013 nicht mehr aktualisiert, es bleibt also spannend 🙂

Selenium RC

Einführung

2004 hat Jason Huggins eine JavaScript-Bibliothek erstellt, die es ihm ermöglichte, einen Browser zu steuern und somit Interaktionen zu automatisieren. Diese wurde später unter dem Namen Selenium Remote Control opensource veröffentlicht. Später entstand Selenium Webdriver, mit welchem im mich im nächsten Beitrag befassen werde.

Selenium RC ist offiziell deprecated. In besonderen Umgebungen, z.B. wenn nur ältere Versionen eines Browsers verwendet werden, kann es nötig sein, Selenium RC weiterhin einzusetzen. Abgesehen davon lässt sich mit Selenium RC schön illustrieren, wie Testskripte und Browser interagieren.

Wie funktioniert Selenium RC?

Selenium RC hat mehrere Bestandteile:

  • Das Core umfasst die JavaScript-Bibliothek, die schlussendlich den Browser steuert.
  • Der Server startet den Browser inklusive der JavaScript-Bibliothek. Danach leitet er sämtliche Befehle vom Testskript an das in den Browser injizierte JavaScript weiter und allfällige Resultate wieder zurück an das Testskript.
  • Die Client Libraries / Bindings bieten Schnittstellen in verschiedenen Programmiersprachen an, um den Server anzusteuern. Sie werden also verwendet, um das Testskript zu implementieren.
Das Testskript (Bindings) ruft den Server auf, dieser leitet die Instruktion an das Selenium Core innerhalb des Browsers weiter, welches sie ausführt. Allfällige Antworten fliessen auf dem selben Weg zurück

Kommunikationsfluss zwischen Testskript, Server und Browser

Weshalb Selenium RC?

Im Vergleich zu Selenium IDE (siehe auch Blogeintrag zu Selenium IDE) bietet Selenium RC viel mehr Möglichkeiten:

  • Es können Schleifen oder bedingte Anweisungen verwendet werden; es ist so möglich, das Testskript über Parameter zu steuern oder auf den Zustand der zu testenden Software zu reagieren. Ein Beispiel ist, die Befehle zum Einloggen auf die zu testende Software nur dann auszuführen, wenn die Applikation auf die Login-Seite weiterleitet.
  • Die Testskripte können automatisch gestartet werden und können so in den Continuous Build integriert werden. So kann auch das GUI regress-getestet werden.
  • Es können auch andere Browser als Firefox gesteuert werden.
  • Da die Kommunikation zwischen dem Testskript und dem Server über HTTP läuft, ist es nicht zwingend notwendig, dass sich beides auf derselben Maschine befindet. Somit lassen sich Selenium-Tests auch remote durchführen.

XPath

Im nachfolgenden Beispiel werden die Elemente auf der Webseite mit XPath, einer Abfragesprache für XML durchgeführt. Selenium erlaubt es auch, die Elemente per CSS anzusprechen. Browser-Plugins erleichtern hier das Entwickeln, z.B. FirePath.

Beispiel eines Testskripts

Im letzten Blogbeitrag habe ich die Exportmöglichkeit von Selenium IDE in verschiedene Formate wie z.B. Java-Source-Code erwähnt und auch folgendes Beispiel abgebildet:

package com.example.tests;

import com.thoughtworks.selenium.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
import java.util.regex.Pattern;

public class SampleTestCase {
    private Selenium selenium;

    @Before
    public void setUp() throws Exception {
        selenium = new DefaultSelenium("localhost", 4444, "*chrome", "https://www.google.ch/");
        selenium.start();
    }

    @Test
    public void testSampleTestCase() throws Exception {
        selenium.open("/");
        selenium.type("id=lst-ib", "Bluesky");
        selenium.click("name=btnG");
        selenium.click("link=Bluesky IT-Solutions AG");
        selenium.waitForPageToLoad("30000");
        verifyEquals("SOFTWARE DEVELOPMENT", selenium.getText("//div[@id='menu']/ul/li[2]/a/div/div"));
    }

    @After
    public void tearDown() throws Exception {
        selenium.stop();
    }
}

Anhand von diesem lassen sich ein paar Punkte gut illustrieren:

  • Das Laden der Seite (nach Absenden der Suchanfrage) muss abgewartet werden. Hier mit der Zeile
    selenium.waitForPageToLoad("30000");

    Übergeben wird der Methode ein Timeout (hier 30s); ist bis dahin die Seite nicht geladen, bricht das Skript ab.

  • technisches Detail: die Testklasse muss von SeleneseTestCase erben, damit sie kompiliert (verifyEquals kann sonst nicht erkannt werden)
  • in der Selenium-IDE hatte ich die Geschwindigkeit mit dem Slider auf langsam gesetzt, dies muss ich im Java-Code noch nachführen, sonst läuft das Skript schneller, als Google suchen kann und resultiert somit in einem Fehler.
    selenium.setSpeed("1000");
  • Das Markup von Google hat sich inzwischen geändert: der Submit-Button hat im Name-Attribut nun nicht mehr den Wert btnG sondern btnK stehen. Wichtig ist also, potentiell mehrfach-verwendete Selektoren zentral zu definieren.
  • Auch die Seite von Bluesky ist nicht mehr dieselbe: der zweite Menüeintrag war vor ein paar Monaten noch SOFTWARE DEVELOPMENT, jetzt ist er DIGITAL PRESENCE. Nun stellt sich die Frage, was wir mit
    verifyEquals("SOFTWARE DEVELOPMENT", selenium.getText("//div[@id='menu']/ul/li[2]/a/div/div"));

    testen wollen:

    • wollen wir sicherstellen, dass der zweite Menüeintrag immer SOFTWARE DEVELOPMENT heissen wird, ist der Test so ok. Der Selektor //div[@id=’menu‘]/ul/li[2]/a/div/div ist sehr spezifisch, d.h. er gibt sehr stark vor, wie die Markupstruktur auszusehen hat. Weniger einschränkend wäre z.B. //*[@id=’menu‘]//li[2].
    • wollen wir mit dem verifyEquals aber nur eine Vorbedingung für den nächsten Testschritt überprüfen, nämlich dass ein bestimmter Menüeintrag vorhanden ist, weil wir damit interagieren wollen, ist der Selektor anzupassen
      verifyTrue(selenium.isElementPresent("//*[@id='menu']//*[contains(text(), 'DIGITAL PRESENCE')]"));

Nach diesen Anpassungen läuft das Testskript erfolgreich durch und sieht folgendermassen aus:

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.thoughtworks.selenium.*;

public class SampleTestCase extends SeleneseTestCase {
    private Selenium selenium;
    private static String googleSubmitButton = "name=btnK";

    @Before
    public void setUp() throws Exception {
        selenium = new DefaultSelenium("localhost", 4444, "*chrome", "https://www.google.ch/");
        selenium.start();
        selenium.setSpeed("1000");
    }

    @Test
    public void testSampleTestCase() throws Exception {
        selenium.open("/");
        selenium.type("id=lst-ib", "Bluesky");
        selenium.click(googleSubmitButton);
        selenium.click("link=Bluesky IT-Solutions AG");
        selenium.waitForPageToLoad("30000");
        verifyTrue(selenium.isElementPresent("//*[@id='menu']//*[contains(text(), 'DIGITAL PRESENCE')]"));
    }

    @After
    public void tearDown() throws Exception {
        selenium.stop();
    }
}

Tipps

  • Robuste Selektoren: In den meisten Fällen verändert sich die zu testende Software über die Zeit. So werden neue Features eingefügt, design-bedingte Wrapper erstellt oder HTML-Tags umgeschrieben. Oft haben diese Änderungen aber nichts mit dem spezifischen Test zu tun. Wenn wir z.B. den Selektor //div[@id=’menu‘]/ul/li[2]/a/div/div verwenden, um einen bestimmten Menüeintrag auszuwählen wird das Testskript failen, sobald die Markup-Struktur des Menüs ändert oder auf der Seite ein neuer Menüeintrag vor dem angestrebten eingefügt wird. Besser ist ein weniger spezifischer Selektor; z.B.  oder noch besser table[@class=’statistics‘] weil der unempfindlicher ist auf Änderungen im weiteren Umfeld.

Grenzen von Selenium RC

  • Die Steuerung durch JavaScript verhält sich nicht immer genau gleich wie die tatsächliche Benutzer-Interaktion mit der Applikation.
  • Da die Steuerung des Browsers mit JavaScript ausgeführt wird kann es zu unterschiedlichem Verhalten bei verschiedenen Browsern kommen, wenn sie das entsprechende JavaScript-Codestück unterschiedlich interpretieren.

Ausblick

In einem nächsten Beitrag werden wir sehen, wie sich Selenium Webdriver von Selenium RC unterscheidet.

Selenium IDE

In diesem ersten Beitrag einer Reihe zu Selenium stelle ich Selenium IDE vor. Die nachfolgenden Beiträge werden sich mit Selenium RC und Selenium WebDriver befassen und in den nächsten Monaten erscheinen.

Einführung

2004 hat Jason Huggins eine JavaScript-Bibliothek erstellt, die es ihm ermöglichte, einen Browser zu steuern und somit Interaktionen zu automatisieren. Diese wurde später unter dem Namen Selenium Remote Control opensource veröffentlicht. Selenium IDE wurde 2006 von Shinya Kasatani erstellt und später dem Selenium Projekt gespendet.

Selenium IDE will auch technisch nicht versierten Nutzern ermöglichen, einfach automatisierte Tests zu erstellen. Sie ist als Firefox Addon erhältlich.

Screenshot Selenium IDE

Screenshot Selenium IDE

Wie funktioniert Selenium IDE?

Sobald sie geöffnet und der Aufnahmemodus gestartet ist zeichnet Selenium IDE sämtliche Interaktionen des Benutzers mit der Webseite auf. Die Benutzeraktionen einer Aufzeichnung werden in einem TestCase zusammengefasst. Im folgenden Beispiel wurden fünf Aktionen aufgezeichnet:

Screenshot eines TestCase

Beispiel TestCase

  1. die Webseite öffnen: die URL wird aus der Base URL und dem Target vom Command zusammengesetzt (http://www.google.ch und /)
  2. den Namen Bluesky ins Suchfeld tippen
  3. den Button namens btnG klicken
  4. in den Suchresultaten auf den Link Bluesky IT-Solutions AG klicken und warten, bis die Seite fertig geladen ist
  5. verifizieren, dass ein Menüeintrag namens SOFTWARE DEVELOPMENT vorhanden ist

Einmal aufgezeichnet lässt sich ein TestCase immer wieder abspielen. TestCases können abgespeichert und auch zu TestSuites zusammengefasst werden. In nachfolgender Grafik sehen wir eine TestSuite, die sich aus vier Testfällen (6-7_1, 6-7_3, 6-7_5 und 6-7_6) zusammensetzt und als Ganzes wieder abgespielt werden kann. Somit können TestCases in mehreren Suites verwendet werden. Ändert sich der getestete Seitenabschnitt, muss dies nur im TestCase angepasst werden; die Neuerung steht dann allen Suiten zur Verfügung.

Screenshot einer TestSuite, welche TestCases gruppiert

TestSuite

Vorstufe für programmierte Testautomatisierungen

Testfälle können aus der Selenium IDE in diverse Sprachen (Java, Ruby, Python) exportiert werden. Der JUnit-Test von obigem Testfall sieht z.B. folgendermassen aus:

package com.example.tests;

import com.thoughtworks.selenium.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
import java.util.regex.Pattern;

public class SampleTestCase {
    private Selenium selenium;

    @Before
    public void setUp() throws Exception {
        selenium = new DefaultSelenium("localhost", 4444, "*chrome", "https://www.google.ch/");
        selenium.start();
    }

    @Test
    public void testSampleTestCase() throws Exception {
        selenium.open("/");
        selenium.type("id=lst-ib", "Bluesky");
        selenium.click("name=btnG");
        selenium.click("link=Bluesky IT-Solutions AG");
        selenium.waitForPageToLoad("30000");
        verifyEquals("SOFTWARE DEVELOPMENT", selenium.getText("//div[@id='menu']/ul/li[2]/a/div/div"));
    }

    @After
    public void tearDown() throws Exception {
        selenium.stop();
    }
}

Hiermit kann gut ein Grundgerüst für einen neuen Test erstellt werden, es bedarf aber noch diverser Verbesserungen um die Wartbarkeit zu gewährleisten.

Persönliche Erfahrung

Ich habe Selenium IDE schon in folgendem Fall verwendet:

  • Aktion war mehrfach auszuführen (für jedes Element aus einer LIste)
  • mühsam zu bewältigen da die zu klickenden GUI-Elemente weit auseinander lagen auf dem Bildschirm
  • einmaliger Einsatz: Aufwand um die Automatisierung zu programmieren lohnte sich nicht

Grenzen von Selenium IDE

Selenium IDE ist ideal, wenn man schnell etwas aufzeichnen und danach wieder abspielen will.

Sie hat aber auch Einschränkungen:

  • nur im Firefox möglich
  • kann nicht in den Entwicklungsprozess integriert werden (z.B. im Continuous Integration Prozess)
  • Selektoren (z.B. „//div[@id=’menu‘]/ul/li[2]/a/div/div„) sind nicht robust: schon kleine Änderungen am Markup führen dazu, dass sie nicht mehr das richtige Element treffen
  • kennt weder Schleifen noch bedingte Anweisungen

 Ausblick

In einem nächsten Beitrag werden wir sehen, wie man – z.B. unter Zuhilfenahme des mit Selenium IDE erstellten Testskripts – automatisierte Tests programmieren kann.

Open Source @ Bluesky

Wir bei bluesky verwenden in der Softwarentwicklung naturgemäss viele open source Komponenten. Wer erfindet schon gerne das Rad immer wieder von neuem?

Trotzdem gibt es immer wieder Situationen, in denen keine geignete Komponente gefunden wird. Häufig findet sich eine Bibliothek, die „beinahe“ passt, aber ein oder zwei kritische Features fehlen. Deshalb sind wir ab und zu „gezwungen“, eine eigene passende Bibliothek zu implementieren. Und wenn das Management will 🙂 dürfen wir diese dann sogar der Community als Open Source Software zur verfügung stellen.

Ich werde deshalb in den nächsten Wochen in loser Folge die von uns unter einer Open Source Lizenz zur Verfügung gestellten Bibliotheken kurz vorstellen.

Ich werde versuchen zu erklären, wieso keine alternative Bibliothek verwendet wurde und was die USPs der umgesetzten Lösung sind.

Aber in medias res – hier unsere erste Open-Source Komponente:

bluesky-configuration

Das Problem

In praktisch jeder Anwendung muss auf externe Konfigurationsinformation zugegriffen werden. Häufig liegt diese Information in einem Properties-File. Properties-Files können aus Java heraus leicht gelesen werden. Leider ist der Zugriff auf Strings beschränkt und es ist unklar, was passiert, wenn die gewünschte Information nicht im Properties-File enthalten ist.

Unsere Lösung soll typsicheren Zugriff auf Konfigurationsinformationen bieten, klar stellen, was passiert, wenn die entsprechende Property in der Konfigurationsdatei nicht gefunden wird und generell leicht und in jeder Umgebung zu verwenden sein (innerhalb eines (EJB-/Web-) Containers oder auch nur in der nackten JVM.

Die Internet-Recherche

Bei einer kurzen Internet-Recherche kommt nicht allzu viel brauchbares heraus: Apache Commons Configuration z.B. Die Lösungen sind aber oft zu schwergewichtig oder haben ein „Late binding“ in dem Sinne, dass die Name der Properties als Strings im Code verstreut sind.

Die Lösung

bluesky-configuration kapselt die Konfigurationsinformation hinter einem Interface:

public interface MyConfiguration {
    String getServerName();

    int getPort();

    boolean getDaemon();
}

Seit geraumer Zeit kennen wir in Java Annotationen, die wir hier verwenden können, um diese Properties an eine Konfigurationsdatei zu „binden“. Gleichzeitig kann auch noch ein Default-Wert angegeben werden:

@Configuration( name="server.properties", prefix="server.base")
public interface MyConfiguration {
    @ConfigProperty( name="servername", value="localhost)
    String getServerName();

    @ConfigProperty( name="port", value="8080")
    int getPort();

    @ConfigProperty( name="daemon", value="false")
    boolean getDaemon();
}

Diese Konfiguration kann nun ganz einfach „gelesen“ werden:

    MyConfiguration config = ConfigurationService.instance().get( MyConfiguration.class);

    String name = config.getServerName();

Hinter dem Vorhang wird nun ein dynamischer Proxy erzeugt, der die Annotationen interpretiert und das Property-File aus verschiedenen Quellen liest.

Mit diesem Mechanismus können nun auf sehr einfache Weise neue Konfigurationsparameter eingeführt und typsicher auf diese zugegriffen werden.

adaptTo() 2014

Apache Sling & Friends Tech Meetup

Kürzlich war ich wieder an der adaptTo() in Berlin. Wie immer echt genial! Die Vorträge waren spannend, die Teilnehmer vorwiegend motivierte Entwickler. Die Speaker meist selber Entwickler und das Beste… man konnte sich während den Pausen direkt mit den Speakern und den Entwicklern vom Adobe Development/Research Team austauschen.

Ich möchte hier nur einige Vorträge erwähnen, für mich die „Highlights“ unter den anderen guten Vorträgen.

Da war der Vortrag von Gaston Gonzalez, welcher spannende Aspekte über die Möglichkeiten der Integration von Apache Solr in AEM gegeben hat oder der Talk von Vivek Sachdeva, welcher eine ElasticSearch Integration präsentierte. Weiter war sicher der Speech von Michael Dürig zum Thema OAK eine spannende Einführung in die neuen Features von Apache Jackrabbit OAK – worüber wir nächstens mehr bei JUG Schweiz hören werden. Weiter die Entwicklungsmöglichkeiten mit Apache Cordova (früher PhoneGap), welche sich aus dem Zusammenspiel mit AEM ergeben von Bruce Lefebvre vorgetragen und zum Schluss die Kombination von IBeacon mit AEM von Bartek Sion. Weitere Themen und alle Folien können auf der AdaptTo() 2014 Seite angesehen werden.

Als weiteren Höhepunkt möchte ich die Hacksession vom Dienstag erwähnen, welche dieses Jahr ausserordentlich gut organisiert wurde. Nach den Vorträgen wurden die Tische in der Kulturbrauerei kurzerhand zu Arbeitsflächen zusammen geschoben. Zu zehn verschiedene Themengebiete wurde in Gruppen gearbeitet bzw. diskutiert. Man konnte sich beliebig seinem Interessengebiet anschliessen.

Vielen Dank an die Organisatoren und bis hoffentlich im nächsten Jahr!

ArchiB@le September – Reactive Manifesto

Am letzten ArchiB@le Treffen haben wir uns zu 7 auf der Hinterhof Terrasse in Basel zum Thema „The Reactive Manifesto“ versammelt. An einem wirklich wunderbaren Spätsommer Abend hat Mario Fredenhagen (Bluesky IT-Solution) über das Reaktive Manifesto erzählt und hat dabei viele anschauliche Beispiele aus der Java Welt gegeben.

Prinzipiell ging es darum das doch sehr Scala lastige Manifesto auf andere Umgebungen, im Speziellen Java EE, zu transportieren. Dazu wurden die Möglichkeiten der JEE im Bezug auf Asynchronität und Messaging aufgezeigt und zudem wurde das Design Pattern Circuit-Breaker als ein Building Block für Resilience diskutiert.

IMG_1072

Bis zum nächsten mal am 7. Oktober – wir freuen uns schon auf das Thema „Microservices“…

6th Lean, Agile & Scrum Conference 2014

Diese Jahr war ich zum ersten Mal an der LAS in Zürich, sehr lohnenswert, fand ich! Tolle Vorträge, tolle Gruppenarbeiten und sehr motivierende Gespräche und spannende Konferenz- Teilnehmer.

Aber der Reihe nach:
Die Konferenz hat mit ein paar interessanten Erläuterungen zum Thema „Adding Discipline to Agile Development“ von Alistair Cockburn begonnen.
Danach konnten sich alle Speaker kurz vorstellen und in einer Minute kurz Werbung für ihren Talk machen. Gute Idee – so bekommt man in kurzer Zeit einen Eindruck und kann sich einfacher für die Sessions entscheiden.

Ich habe mich für den Vortrag von Steve Holyer „Transforming Addicted Organisations“ entschieden. Es ging darum, alte Muster aufzubrechen und Veränderungen bzw. Verbesserungen in eine Organisation einfliessen zu lassen. Anhand zweier Gruppenarbeiten wurde aufgezeigt, wie wiederkehrende Muster relativ einfach erkannt werden können. Die Session war spannend, leider haben sich ausser mir noch 60 weitere Personen für diesen Talk entschieden. Somit war der Raum etwas gar voll und bei den Gruppenarbeiten war die Zeit sehr knapp bemessen, mit je 8-10 Teilnehmern in der Gruppe.

Als nächstes war ich an der Session von Christian Dähn und Ilja Preuß „In einfachen Schritten die Unternehmenskultur ändern“. Ein spannender Talk zur Verbesserung der Unternehmenskultur. Die Mitarbeiter sollen sich wohl fühlen, gerne im Unternehmen arbeiten und somit auch bleiben.

Nach einem Stehmittagessen, welches viel Platz für den Austausch mit anderen Teilnehmern der Konferenz bot, ging es am Nachmittag mit zwei Fishbowle Sessions weiter.
Das heisst, es wurden im Vorfeld Themen gesammelt. Die acht meist gewählten wurden nun in je 2 mal 4 parallelen Fishbowles abgehalten. Ich war an den Bowls „Sind jährliche MAG’s eine Farce?“ und „Schätzen ist Zeitverschwendung“. Mein Take-Away bei der ersten Bowle war: „MAG’s führen mit den Leuten, welche du dir selber auswählst“ und bei der zweiten „Es spielt keine Rolle, ob eine Story 2 oder 3 Storypoints gross ist, wichtig ist das Big-Picture“.

Als letzten Vortrag wählte ich das Thema „Lösungsorientierte Retrospektiven“ von Ralph Miarka und Veronika Kotrba. Besonders dieser Talk gab mir viel Input für meine nächsten Retros.

Nach den Closing Keynotes von Bob Marshall habe ich beim Apéro wieder sehr interessante Diskussionen über das gerade gehörte führen können…

Alles in allem, war die LAS für mich ein sehr anregender und motivierender Tag!

 

Frontend Conference 2014

Die FrontendConf war auch dieses Jahr ein erfreulicher Anlass für mich.

Die Vorträge deckten viele Themen ab:
Lehrreich fand ich den Vortrag zum Styling von E-Mails, auch wenn mein Frontender-Herz blutet, wie dabei Styles und Markup vermischt werden müssen.
Die Vorträge zu ECMAScript 6 und CSS-Grids gewährten interessante Ausblicke und liessen Vorfreude aufkommen. ECMA-Script 6  wird JavaScript verständlicher, weniger fehleranfällig und somit  hoffentlich zugänglicher für Entwickler von anderen Sprachen machen.
Peter-Paul Koch lieferte einen guten Überblick über Mobile Viewports; nebst der Erklärung, wie man sie verwenden soll ging er auch stark darauf ein wieso. Mit seiner geübten Vortragstechnik liess er uns alle vergessen, dass es der erste Vortrag frühmorgens nach der tollen Konferenzparty war.
Noch völlig unvertraut war ich mit dem Thema WebRTC. Szymon Nowak hat dazu viele spannende Projekte vorgestellt, so etwas sharedrop.io, das einen Datenaustausch ähnlich zu AirDrop  für alle Geräte ermöglicht.
Spannend fand ich, wie das Smashing-Magazine die Performance seiner Seite optimiert hat. Der Talk von Tim Kadlec zielte in dieselbe Richtung und mitgenommen habe ich von ihm den Tipp, die Performance für den Entwickler ständig sichtbar zu machen, d.h. dass grad während der Entwicklung ersichtlich wird wenn „teure“ Features hinzukommen.

Nicht nur die Vorträge waren interessant, die Organisatoren haben in allen Bereichen tolle Arbeit geleistet. So etwa bei der Location, der Verpflegung (toller Kaffee!) und der Infrastruktur. Ich freue mich schon auf die FrontendConf 2015.

Adobe Experience Manager (AEM) Developer Tools – How to convert exisiting project

The “AEM Developer Tools” is an eclipse plugin that offers several features to make AEM development easier. You can for example easily synchronize content and OSGI bundles. I will show you how easy it is to enable this features on existing projects.

  1. Download and install the AEM developer tools. For more information read the adobe docs http://docs.adobe.com/content/docs/en/dev-tools/aem-eclipse.html
  2. Open the AEM perspectiveEclipse - Open AEM Perspective
  3. Create a new server instance.Create new server instance 1To do this, click the link in the server view.Create new server instance 2Choose Adobe Experience Manager as server type.Create new server instance 3You don’t need a resource yet. We will add the resources later, after importing the project in our workspace. Just click Finish. After that you should see the newly configured server in the server view.Create new server instance 4
  4. Open the server configuration page by double clicking on the server instance in the server view. Adjust the port and debug port (eg. 4502 / 8000). Do not forget to save the file!Edit AEM server configuration
  5. Import your existing project with the import dialog.Import existing project 1 Import existing project 2Import existing project 3
  6. After the import, start your local AEM instance. Then go back in the server configuration and click „install“ next to “Installation support bundle is not present or outdated, deployment will not work”. The deployment should now works.Install support bundle
  7. Now you are able to add the bundle project to your Adobe Experience Manager instance. To try this, right click your AEM instance in the server tab and click “Add and Remove”. Choose the bundle project and click add. Then press finish. At this time all changes in the bundle project will be synchronized with the aem instance. You can check this by looking at the OSGI-Bundles in the Felix console. After you made changes on the java code the bundle timestamp should be updated.Add bundle project 1Add bundle project 2
  8. Now there is one point missing. The content project must also be synchronized with the CRX. To reach that goal you have to convert your content project. Right-click on the content project and click Configure. Then you must choose “Convert to Content Project”. Now a dialog appears where you must select the content folder (the folder that contains your  jcr_root node). Select the folder and click “OK”.Convert to content project 1Convert to content project 2
  9. After converting, you are finally able to add the content project to your AEM instance.Add content project
  10. After adding the content project to the AEM server instance you can now synchronize the changes from and to the repository. To make an initial export to the server, click on your content project and select “AEM -> Export to server”.Export to server
  11. After the click a dialog appears and shows a summary to which server the content should be exported. Click Finish. Export to server 2

That’s it! After this configuration you don’t need a deployment to bring your changes to AEM.