Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Schnelle und leichtgewichtige Anwendungsentwicklung mit HTML5 und JEE/REST (JUG Fffm)

Schnelle und leichtgewichtige Anwendungsentwicklung mit HTML5 und JEE/REST (JUG Fffm)

Präsentiert bei der Java User Group in Frankfurt. Jetzt ein erweitereter Vortrag im Vergleich zur Version in Berlin. Auf Anregung diesmal auch mit Live-Coding.

Alexander Schwartz

June 26, 2013
Tweet

More Decks by Alexander Schwartz

Other Decks in Programming

Transcript

  1. Schnelle und leichtgewichtige Anwendungsentwicklung
    mit HTML5 und JEE REST
    Alexander Schwartz
    Java User Group Frankfurt / 26. Juni 2013
    1 © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz

    View Slide

  2. 2
    Was ich vorhabe
    1. Worum es geht
    2. Fachlicher Einstieg in das Beispiel
    3. JEE Stack für REST auf dem Server
    4. HTTP + JavaScript Stack auf dem Client
    5. Testen der Anwendung
    6. Detaillierung Server-Tests
    7. Detaillierung Client-Tests
    8. Zusammenfassung
    © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz

    View Slide

  3. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    3
    Worum es hier geht
    • HTML als Seitenbeschreibung
    • CSS für ansprechendes (responsive) Design
    • Widget z.B. via jQueryUI + Plugins
    • Clientlogik via JavaScript
    • Strukturierung mit Javascript MV*-Frameworks
    (z. B. KnockoutJS)
    • Modularisierung und Nachladen von Resourcen
    (z. B. requireJS)
    • JAX-RS 1.0/2.0 als Teil von JEE 6/7
    • Kommunikation via REST/JSON ideal für JavaScript
    • Persistenz via JPA
    • Validierung von Daten mit Bean Validation
    • CDI für Erweiterungspunkte
    • Integration in Enterprise IT dank vieler Java-Bibliotheken
    Browser als
    Client-Plattform
    JEE REST für
    serverseitige
    Services
    HTML+JavaScript und JEE+REST als Plattform

    View Slide

  4. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    4
    Mein Sponsor und Arbeitgeber
    1980 gegründet
    mehr als 4000 Kollegen
    8 Branchen
    540 Mio € Umsatz 2012
    22 Länder
    16 deutsche
    Standorte
    msg systems ag

    View Slide

  5. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    5
    Wer ich bin
    Alexander Schwartz
    Lead IT Consultant im GB Travel und Logistics
    10 Jahre Java
    7 Jahre PL/SQL
    7 Jahre
    Absatzfinanzierung
    3,5 Jahre Direktbank
    1 Frau
    2 Kinder
    272 gefundene
    Geocaches

    View Slide

  6. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    6
    User Story:
    „Nutzer möchte die Sichtung eines Schiffes
    erfassen, um später sehen zu können, ob auch
    andere dieses Schiff gesehen haben.
    Hierzu erfasst er Schifftstyp, Datum,
    Zeitzone und eine Notiz.“
    Die heutige Aufgabe
    Online-Datenbank für (Raum-)Schiffsichtungen
    Garantiert kein
    Bezug zu
    einem
    Kundenprojekt!
    https://github.com/ahus1/rest-samples

    View Slide

  7. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    7
    Unser Wegweiser
    • Darstellung User-Interface
    • Interaktion mit dem Nutzer
    V
    View
    • Datenhaltung im Client
    • Bindung an den View
    M
    View Model
    • Kommunikation zwischen Server/Client
    • Besteht aus server- und clientseitigem Teil
    C
    Communication
    • Fachliche Business-Logik
    • Greift auf Persistenz zu
    B
    Business Services
    • Datenhaltung und Persistenz
    P
    Persistence
    Eine klare Schichtentrennung hilft als Wegweiser durch die Architektur
    Client Server

    View Slide

  8. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    8
    Was es im Inneren zusammenhält
    Sichtung
    Schiffstyp
    Zeitzone
    Domain-Model für Struktur hilft Fachabteilung und Entwicklern
    M
    C
    P
    Client Server

    View Slide

  9. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    9
    Wie´s für den Kunden aussieht
    Mockups klären früh das Maskenlayout und verringern Nacharbeiten
    P
    Client Server
    V

    View Slide

  10. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    10
    • IDs werden automatisch generiert
    • Validierung über Bean-Validation
    • Basis-Klasse AbstractEntity für Optimistic Locking
    Los geht‘s – die erste Entität
    Standard-JPA-Entität für „Zeitzone“
    P
    Client Server
    @Entity
    public class Timezone extends AbstractEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long timezoneId;
    @NotEmpty
    private String timezoneName;

    }
    @MappedSuperclass
    public class AbstractEntity {
    @Version
    private Integer version;

    }

    View Slide

  11. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    11
    • Übersetzbares Element als Entität Translation
    • CascadeType.ALL für gemeinsame Speicherung
    • Orphan Removal für Housekeeping
    • Translation enthält eine Map mit Übersetzungen
    Entität mit Übersetzung
    Komplexe Entität „Schiffstyp“
    P
    Client Server
    @Entity
    public class Vessel extends AbstractEntity {
    @Id
    @GeneratedValue
    (strategy = GenerationType.IDENTITY)
    private Long vesselId;
    @OneToOne(fetch = FetchType.EAGER,
    cascade = CascadeType.ALL,
    orphanRemoval = true)
    @JoinColumn(name = "vesselName")
    private Translation vesselName;

    }
    @Entity
    public class Translation extends AbstractEntity {
    @Id
    @GeneratedValue
    (strategy = GenerationType.IDENTITY)
    private Long translationId;
    @ElementCollection
    @CollectionTable(name = "Text", joinColumns =
    @JoinColumn(name = "translationId"))
    @MapKeyColumn(name = "textLanguage")
    @Column(name = "textString")
    private Map texts;

    }

    View Slide

  12. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    12
    Vorsicht beim (Daten-Model) Bau
    Abbildung fachlicher Datentypen auf technische Datentypen
    Fachlich Java JSON JavaScript
    Zeichenkette String String String
    Ganzzahl Long Number Number
    Dezimalbruch BigDecimal String * String *
    Datum LocalDateTime String ** String **
    * JavaScript Number-Type unterstützt nur Fließkommazahlen, aber keine Dezimalzahlen. Es
    können dadurch Rundungsdifferenzen auftreten, die fachlich nicht gewünscht sind. Daher
    Fallback auf String.
    ** „Standard“ bei JSON ist für Datumsangaben Sekunden seit 1970 und Zeit UTC.
    LocalDateTime lässt sich so nicht abbilden; Date in JavaScript wird in der Zeitzone des
    Browser dargestellt => keine Kontrolle durch Anwendung möglich möglich. Daher Fallback auf
    Datum als String im ISO-Format
    M
    C
    P
    Client Server

    View Slide

  13. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    13
    • ManyToOne-Relation für Selectbox Vessel – ohne Cascade!
    • Joda-Elemente für Zeiten; usertype für Joda-Persistenz
    Datum in JPA
    Komplexe Entität „Sichtung“
    P
    Client Server
    @Entity
    public class Sighting extends AbstractEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long sightingId;
    private String sightingMemo;
    @ManyToOne
    @JoinColumn(name = "vesselId")
    private Vessel vessel;
    @Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTimeZoneAsString")
    private DateTimeZone sightingTimezone;
    @Type(type = "org.jadira.usertype.dateandtime.joda.PersistentLocalDateTime")
    private LocalDateTime sightingDate;

    }

    View Slide

  14. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    14
    • DefaultRestEndpoint liefert CRUD Funktionalität
    • Genug „Platz“ im Endpoint für spezifische Funktionalität
    (z.B. Aufruf von Business Services)
    • Sicherstellung „Don‘t Repeat Yourself“
    Erster REST Endpoint
    Java-Generics sind gut!
    @Stateless
    @Path("/timezone")
    public class TimezoneEndpoint extends DefaultRestEndpoint {
    }
    Client Server
    C
    @Produces({ "application/json", "text/xml" })
    @Consumes({ "application/json", "text/xml" })
    public abstract class
    DefaultRestEndpoint {
    < … 500 Zeilen Generics, Reflection, JPA Metamodel,
    JavaDoc … Einblick auf der nächsten Folie … >
    }

    View Slide

  15. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    15
    Blick durch Schlüsselloch in DefaultRestEndpoint
    Client Server
    C
    public abstract class DefaultRestEndpoint {

    @GET
    @Path("/{id:.+}")
    public Response findById(@PathParam("id") String id, @Context Request
    request) {
    ENTITY result = em.find(getEntityClass(), constructPK(id));
    if (result == null) {
    throw new EntityNotFoundException();
    }
    pullByJsonView(result, getExtendedView());
    return Response.ok(result).build();
    }

    public abstract class DefaultRestEndpoint {

    @POST
    @Path("")
    public Response add(ENTITY entity) {
    bindReadOnlyEntities(entity);
    em.persist(entity);
    em.flush();
    UriBuilder locationBuilder = uriInfo.getBaseUriBuilder();
    locationBuilder.path(this.getClass());
    PersistenceUnitUtil puu = em.getEntityManagerFactory()
    .getPersistenceUnitUtil();
    URI childLocation = locationBuilder.path("{id}").build(
    puu.getIdentifier(entity));
    return Response.status(Response.Status.CREATED).location(childLocation)
    .build();
    }

    public abstract class DefaultRestEndpoint {
    ….
    @POST
    @Path("/qbe")
    public List queryByExample(ENTITY entity) {
    Session session = (Session) em.getDelegate();
    Example example = Example.create(entity).enableLike(MatchMode.ANYWHERE)
    .ignoreCase();
    Criteria criteria = session.createCriteria(entity.getClass()).add(example);
    addSubCriteria(criteria, entity);
    if (criteria.list().isEmpty()) {
    return null;
    } else {
    pullByJsonView(criteria.list(), getExtendedView());
    return criteria.list();
    }
    }

    View Slide

  16. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    16
    Object Graph Traversal
    Client Server
    C
    @Stateless
    @Path("/sighting")
    public class SightingEndpoint extends DefaultRestEndpoint {
    @Override
    protected Class> getExtendedView() {
    return Sighting.Extended.class;
    }
    @Override
    @GET
    @Path("/{id:.+}")
    @JsonView(Sighting.Extended.class)
    public Response findById(@PathParam("id") String id,
    @Context Request request) {
    return super.findById(id, request);
    }

    }
    Mit @JsonView-Annotationen kann die Sichtbarkeit eingeschränkt werden
    public abstract class
    DefaultRestEndpoint {
    @GET
    @JsonView(ListView.class)
    public Response listAll() {

    }
    public class Sighting extends AbstractEntity {

    @JsonView(Extended.class)
    public String getSightingMemo() {
    return sightingMemo;
    }

    }

    View Slide

  17. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    17
    • Fachliche Überlegung: kein sightingMemo in der Übersicht notwendig
    • Technische Überlegung: kein version in der Übersicht notwendig
    • ABER: @JsonView gibt‘s nur bei Jackson (nicht JEE Standard)
    Object Graph Traversal Output
    Client Server
    C
    GET http://localhost:8080/rest-samples/rest/sighting
    [{"sightingId":1,
    "vessel":{"vesselId":1,"vesselName":"Klingonischer Jäger"},
    "sightingTimezone":"Europe/Berlin",
    "sightingDate":"2013-04-11T11:00:00.000"},
    {"sightingId":2,
    "vessel":{"vesselId":1,"vesselName":"Klingonischer Jäger"},
    "sightingTimezone":"Europe/London",
    "sightingDate":"2013-04-11T22:00:00.000"}]
    In der Liste sind weniger Attribute angezeigt, in der Einzelansicht mehr
    GET http://localhost:8080/rest-samples/rest/sighting/-1
    {"version":1,
    "sightingId":1,
    "sightingMemo":"unheimlich!",
    "vessel":{"version":0,"vesselId":-1,"vesselName":"Klingonischer Jäger"},
    "sightingTimezone":"Europe/Berlin",
    "sightingDate":"2013-04-11T11:00:00.000"}

    View Slide

  18. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    18
    Erweiterungspunkt: Custom Serialisierer
    Client Server
    C
    public class DateTimeZoneDeserializer extends
    JsonDeserializer {
    @Override
    public DateTimeZone deserialize(JsonParser jparse,
    DeserializationContext context) throws IOException {
    String text = jparse.getText();
    if (text == null || text.trim().length() == 0) {
    return null;
    } else {
    return DateTimeZone.forID(text);
    }
    }
    }
    DateTimeZone serialisieren (da kein Standardtyp)
    public class DateTimeZoneSerializer extends JsonSerializer {
    @Override
    public void serialize(DateTimeZone value, JsonGenerator jgen,
    SerializerProvider provider) throws IOException {
    jgen.writeString(value.getID());
    }
    }
    • Ist kein Standardtyp
    • Eigener Serialisierer kann eingebunden werden

    View Slide

  19. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    19
    • Serialiserer für DateTimeZone und BigDecimal registrieren
    Erweiterungspunkt: Custom Serialisierer
    Client Server
    C
    @Provider
    public class CustomObjectMapper implements ContextResolver {
    @Override
    public ObjectMapper getContext(Class> type) {
    final ObjectMapper result = new ObjectMapper();
    SimpleModule module = new SimpleModule(getClass().getName(), new Version(1,
    0, 0, null))
    .addDeserializer(BigDecimal.class, new BigDecimalAmountDeserializer())
    .addSerializer(BigDecimal.class, new BigDecimalAmountSerializer())
    .addDeserializer(DateTimeZone.class, new DateTimeZoneDeserializer())
    .addSerializer(DateTimeZone.class, new DateTimeZoneSerializer());
    result.registerModule(module);
    result.configure(Feature.WRITE_DATES_AS_TIMESTAMPS, false);
    return result;
    }
    }
    Registrieren der Serialisierer / De-Serialisierer

    View Slide

  20. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    20
    Exception Handler
    Client Server
    C
    @Provider
    public class EntityNotFoundExceptionMapper implements
    ExceptionMapper {
    @Inject
    private Localizer localizer;
    @Override
    public Response toResponse(EntityNotFoundException exception) {
    Map responseObj = new HashMap();
    responseObj.put("general", localizer.localize("error.entityNotFound"));
    return Response.status(Response.Status.NOT_FOUND).entity(responseObj)
    .build();
    }
    }
    Für jede Exception kann (muss) ein eigener Handler definiert werden
    public class Localizer {
    @Inject
    private HttpServletRequest httpServletRequest;
    public String localize(String key) {
    try {
    ResourceBundle rb = ResourceBundle.getBundle("messages",
    httpServletRequest.getLocale());
    return rb.getString(key);
    } catch (MissingResourceException e) {
    return "{" + key + "}";
    }
    }
    }

    View Slide

  21. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    21
    Validierung von Daten
    Client Server
    C
    Bean Validation plus Exception-Handler
    #ValidationMessages_de.properties
    sighting.memo.minLength=Muss mindestens {min} Zeichen lang sein
    @Entity
    public class Sighting extends AbstractEntity {

    @NotNull
    @Size(min = 2, message = "{sighting.memo.minLength}")
    private String sightingMemo;

    }
    @Provider
    public class ConstraintViolationExceptionMapper implements
    ExceptionMapper {
    @Override
    public Response toResponse(ConstraintViolationException exception) {
    Map responseObj = new HashMap();
    for (ConstraintViolation> violation : exception.getConstraintViolations()) {
    // … < 40 Zeilen Code > …
    }
    return Response.status(Response.Status.BAD_REQUEST).entity(responseObj)
    .build();
    }
    P

    View Slide

  22. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    22
    • Querschnittsfunktionen lassen sich einfach von domänenspezifischen
    Elementen trennen
    • APIs und Erweiterungspunkte für spezifische Implementierungen sind
    vorhanden
    • JSON Serialisierung ist nicht in JEE 6.0 standardisiert
    • Durch Generics, JPA Metamodel und Reflection gelingt es, das DRY
    Prinzip durchzuhalten
    JEE Zwischenfazit
    Client Server
    C
    JEE REST: JAX-RS
    P

    View Slide

  23. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    23
    Anforderungen:
    • HTML für den View
    • View-Model für Datenhaltung
    • Bi-direktionales Datenbinding View / View-Model
    • Modularisierung von JavaScript-Bibliotheken, aber auch Templates
    und JavaScript-Code für Usecases der Anwendung
    • Stateful-URLs innerhalb der Anwendung; Vor-/Zurück-Navigation und
    direkter Einsprung
    Einstieg HTML
    Client Server
    HTML Single Page Apps – aber bitte strukturiert und mit Modularisierung
    V
    M

    View Slide

  24. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    24
    Beispiel: Eingabefelder mit Label und Eingabefeld
    HTML im View
    Client Server
    CSS-Frameworks wie Bootstrap erlauben schlankes HTML
    V


    Zeitzone bearbeiten


    Name







    View Slide

  25. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    25
    • Reduktion der Information
    • Alternative Anordnung der Information
    HTML im View
    Client Server
    Responsive Design abhängig vom Endgerät/Bildschrimbreite
    V

    View Slide

  26. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    26
    Umgesetzt mit KnockoutJS
    View-Model
    Client Server
    Ein Menü anzeigen – Trennung View vom View Model
    V
    // menu.js
    var Menu = function() {
    // Data
    var self = this;
    self.folders = ko.observableArray([ {
    name : 'Schiffstypen',
    link : '#/vessel/main'
    }, {
    name : 'Sichtungen',
    link : '#/sighting/main'
    }, {
    name : 'Zeitzonen',
    link : '#/timezone/main'
    } ]);
    self.folder = ko.observable();
    }


    data-bind="text: $data.name, attr: {href:
    $data.link}">

    M

    View Slide

  27. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    27
    Eine Texteingabe im Input-Feld aktualisiert das Modell – eine Änderung
    im Modell aktualisiert den View
    View-Model
    Client Server
    Bidirektionales Binding
    V

    self.deleteLanguage = function(language) {
    self.vessel().vesselName.remove(language);
    };
    M

    $parents[2].deleteLanguage">


    View Slide

  28. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    28
    Eine Texteingabe im Input-Feld aktualisiert das Modell – eine Änderung
    im Modell aktualisiert den View
    Berechnete Elemente für Internationalisierung
    Client Server
    Wenn sich die Sprache ändert, ändern sich alle Übersetzungen
    V
    M
    /* knockout.i18n.js */
    ko.i18n = function(key) {
    return ko.computed(function() {
    if (ko.language() != null) {
    return i18next.t(key, {
    lng : ko.language()
    });
    } else {
    return "";
    }
    }, key);
    };

    data-bind="click: $parent.saveVessel, text:
    ko.i18n('glb.save')">
    data-bind="click: $parent.goToMain, text:
    ko.i18n('glb.cancel')">

    View Slide

  29. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    29
    Damit kann an jedem Use Case noch unabhängiger gearbeitet werden
    Modularisierte Resource-Dateien
    Client Server
    Jeder Use Case kann eine eigene Datei bekommen
    V

    data-bind="text: ko.i18n('vessel:vessel.name')">

    data-bind="click: $parent.saveVessel, text: ko.i18n('glb.save')">
    data-bind="click: $parent.goToMain, text: ko.i18n('glb.cancel')">

    View Slide

  30. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    30
    • Jedes Modul erhält einen „Header“ mit Abhängigkeiten
    • Für 3rd-Party-Bibliotheken werden im der Startprozedur
    Abhängigkeiten definiert
    • requireJS sorgt für parallelen Download der JS-Module
    Modularisierung (Model)
    Client Server
    Modularisierung der Anwendung (Model) mit requireJS
    V

    define(
    [ 'knockout', 'jquery', 'mapping', 'hasher',
    'crossroads', 'menu' ],
    function(ko, $, mapping, hasher, crossroads,
    menu) {
    // logik…
    });
    M
    //main.js
    require.config({
    shim : {
    jquery : {
    exports : "jQuery"
    },
    knockout : {
    deps : [ 'jquery' ]
    },
    'knockout.validation' : {
    deps : [ 'knockout' ]
    },…

    src="js/libs/require.js">

    View Slide

  31. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    31
    Modularisierung (Usecases)
    Client Server
    Modularisierung der Use-Cases
    V
    M
    übergreifende Module
    Bibliotheken
    ein Template pro Use Case
    eine JS Datei pro Use Case

    View Slide

  32. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    32
    • HTML5 unterstützt das „History“ API, bei dem URLs sich ändern
    können, auch wenn die Seite gleich bleibt
    • Zusatzinformationen zu einer Seite können per JavaScript in der
    Browser-Historie abgelegt werden
    Ohne History-API:
    • Workaround: URL hinter dem Hash-Tag
    http://localhost:8080/rest-samples/#/vessel/edit/1
    http://localhost:8080/rest-samples/#/vessel/main
    http://localhost:8080/rest-samples/#/timezone/edit/1
    • Unterstützt z.B. durch Crossroads.js
    Stateful URLs
    Client Server
    URLs für den direkten Einstieg – und Vor-/Zurücknavigation
    V
    crossroads.addRoute(/vessel\/edit\/(.+)$/, function(id) {
    $.get("rest/vessel/" + id, function(data) {
    self.vessel(mapping.fromJS(toViewModel(data)));
    self.vesselList(null);
    });
    });

    View Slide

  33. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    33
    • Laden eines Elements
    • Das Model kann ggf. für
    den View punktuell
    transformiert werden,
    z.B. HashMap als Array
    REST-Anbindung in JavaScript
    Client Server
    Das Model im Backend kann weitgehend beibehalten werden
    $.get("rest/vessel/" + id, function(data) {
    self.vessel(mapping.fromJS(toViewModel(data)));
    self.vesselList(null);
    });
    function toViewModel(data) {
    data = jQuery.extend(true, {}, data);
    var text = [];
    $.each(data.vesselName, function(key, value) {
    text.push({
    textLanguage : key,
    textString : value
    });
    });
    data.vesselName = text;
    return data;
    }
    C
    M
    M

    View Slide

  34. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    34
    • Querschnittsfunktionen lassen sich einfach von domänenspezifischen
    Elementen trennen
    • APIs und Erweiterungspunkte für spezifische Implementierungen sind
    vorhanden
    • Die Zahl der Bibliotheken und APIs ist deutlich größer als im JEE
    Bereich
    • Ist der Rahmen vorbereitet, können einfach neue Use Cases
    dazuentwickelt werden (je eine JS + HTML Datei pro Use Case)
    • Code-Änderungen sind nach einem Browser-Refresh sofort sichtbar
    HTML/JS Zwischenfazit
    Client Server
    HTML + JavaScript können strukturiert werden!
    V
    M
    C

    View Slide

  35. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    35
    Automatisiertes Testen
    Client Server
    Verschiedene Testframeworks decken verschiedene Bereiche ab
    V
    M
    C
    B
    P
    Jasmine,
    Sinon
    Selenium
    IDE
    Selenium
    RC
    Junit
    Arquillian
    Arquillian
    +
    REST-
    assured
    Mock
    oder
    echt?
    Mock
    oder
    echt?
    geringe Komplexität
    hohe Komplexität

    View Slide

  36. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    36
    Arquillian:
    • Automatisiertes
    Deployment von
    Teilen der
    Server-Anwendung
    (ggf. ergänzt um
    Mock-Komponenten)
    REST-assured:
    • Testen der
    REST-services
    mit Fluent API
    Arquillian + REST assured
    Client Server
    Test-Anwendungen automatisiert packen und laufen lassen
    @RunWith(Arquillian.class)
    public class MesseEndpointTest {
    @Deployment
    public static WebArchive createArchiveAndDeploy() {
    WebArchive war = ShrinkWrap.create(WebArchive.class,
    "arquillian-rest-demo.war");
    war.addPackages(…);
    war.addAsLibraries(…);
    return war;
    }
    @Test
    public void testReturnFilledList() throws Exception {
    Response r = given().log().all()
    .contentType(ContentType.JSON).expect()
    .body("[0].meBezeichnung", equalTo("Vessel 1"))
    .statusCode(Status.OK.getStatusCode()).when()
    .get("/rest-samples/rest/vessel");
    assertThat("only one element exists",
    r.body().jsonPath().getList("").size(), equalTo(1));
    }
    B
    P
    C

    View Slide

  37. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    37
    Kleine Tests:
    • Unit-Tests für JavaScript-Code-Bibliotheken
    • Ergänzt durch HTML-Fragmente
    • DOM-Interaktion möglich durch jQuery Integration
    Große Tests:
    • Tests der vollständigen Use Cases
    Jasmine BDD Testframework
    Client Server
    Anforderungen beschreiben und Tests automatisieren auf dem Client
    V
    M
    describe("Manage Vessels", function() {
    it("shows a list of two vessels at the start",
    function() {
    expect($("#vesselList")).toBeVisible();
    expect($("#vesselList > tbody > tr")[0]).toContainHtml("Vessel 1");
    expect($("#vesselList > tbody > tr")[1]).toContainHtml("Vessel 2");
    });
    });

    View Slide

  38. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    38
    Frontend-Entwickler ist unabhängig vom Backend – und kann selber
    Testen
    Sinon.JS für Mocks
    Client Server
    Backend kann via JavaScript simuliert werden
    describe("Manage Vessels", function() {
    beforeEach(function() {
    server = sinon.fakeServer.create();
    server.respondWith("GET", "rest/vessel", [ 200, {
    "Content-Type" : "application/json"
    }, vesselList ]);
    server.respondWith("DELETE", "rest/vessel/1", [ 204, null, "" ]);
    server.respondWith("GET", "rest/vessel/1", [ 200, {
    "Content-Type" : "application/json"
    }, vessel ]);
    afterEach(function() {
    // disable fake server
    server.restore();
    });
    );
    C

    View Slide

  39. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    39
    • 7 Tests
    • 760 ms
    Gesamtlaufzeit
    • Cross-Browser
    • Unabhängig vom
    Backend
    • Dokumentation
    aus fachlicher
    Sicht
    • Beliebige
    Schachtelung
    • Chrome etwas
    schneller als
    Firefox
    Jasmine ist schnell und einfach
    Client Server
    Ein Browser-Reload lässt die Tests erneut laufen
    C
    V
    M

    View Slide

  40. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    40
    • Integration in CI
    Server möglich
    • Jasmine Tests erstellen
    XML entsprechend JUnit
    (für Jenkins, Eclipse et al)
    $ phantomjs phantomjs-testrunner.js \
    http://localhost:8080/rest-samples/?spec=
    Testen in der Dunkelverarbeitung
    Client Server
    Mit PhantomJS auf der Kommandozeile testen
    C
    V
    M

    View Slide

  41. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    41
    • Verbinden mit einer laufenden Browser-Instanz
    • Breakpoint setzen, Variablen sehen
    • Hot Code Replacement
    Debugging mit Chome
    Client Server
    Wie Java und ein bisschen mehr?
    V
    M

    View Slide

  42. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    42
    Debugging mit Chome

    View Slide



  43. ...
    © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    43
    Application Cache
    Client Server
    Resourcen werden vorab geladen und über eine Datei validiert
    V
    # cache.appcache
    CACHE:
    /rest-samples/index.html
    /rest-samples/js/main.js
    /rest-samples/js/libs/jquery.js
    /rest-samples/css/libs/bootstrap.css

    NETWORK:
    *
    # hash:a0d1f5…eedd
    • Der Browser erfährt, welche Resourcen er vorab laden soll
    • Daten werden lokal gespeichert
    • Validierung via Manifest, ob Resourcen erneut geladen werden sollen
    (ggf. erst aktivieren, wenn Entwicklung abgeschlossen ist)
    M

    View Slide

  44. © msg systems ag, 26. Juni 2013
    HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz
    44
    • Backend und Frontend können fachliche Komponenten und
    technische Komponenten von einander getrennt werden
    • Steht der Rahmen, so können Entwickler an unabhängig an
    verschiedenen Use Cases arbeiten
    • Steht der Rahmen, so können Entwickler mit geringen
    Vorkenntnissen in die Entwicklung einsteigen
    • Frontend und Backend können separat entwickelt werden
    • HTML+JS bietet schnelle Turnaround-Zeiten in der Entwicklung
    • JEE REST bietet Integration in Enterprise IT und stabile
    Laufzeitumgebung
    • Sowohl Frontend als auch Backend können einfach skalieren
    • Durch neue HTML5 Features wie Application Cache kann die
    Skalierung weiter erhöht werden
    Zusammenfassung
    Client Server
    JEE REST Backend ergänzt sich mit HTML/JS Frontend
    V
    M
    C
    B
    P

    View Slide

  45. www.msg-systems.com
    Vielen Dank für Ihre Aufmerksamkeit
    msg systems ag
    Mergenthalerallee 73 - 75
    65760 Eschborn
    Telefon: +49 (171) 5 62 57 67
    E-Mail: [email protected]
    www.msg-systems.com
    45 HTML5 und JEE REST / JUG Frankfurt / Alexander Schwartz © msg systems ag, 26. Juni 2013

    View Slide