Top Banner
Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency Injection klassisch Dependency Injection was kennen wir bereits CDI im Detail – Aktivierung – Qualifier Event Handling Objekte injizieren – Produzenten – Alternativen – Interception • Fazit Komponentenbasierte Software- Entwicklung
176

6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Jun 04, 2018

Download

Documents

donhan
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

569

6. Contexts and Dependency Injection

• klassisch Dependency Injection

• was kennen wir bereits

• CDI im Detail

– Aktivierung

– Qualifier

– Event Handling

– Objekte injizieren

– Produzenten

– Alternativen

– Interception

• Fazit

Komponentenbasierte Software-Entwicklung

Page 2: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

570

Einschub: aktueller Stand

• Sprinter ist eine klassisch aufgebaute JEE-Applikation

• wir arbeiten mit Klassen und Objekten davon

• kritisch betrachtet sind wesentliche Teile der Software nicht objektorientiert

– oftmals gibt es (pro Nutzer) genau ein Objekt von Steuerungsklassen (alles Singleton, Ausnahme Datenschicht)

– Teilprogramme rufen Methoden (?? Prozeduren) in anderen Teilprogrammen auf

• (Oracle Application Express (APEX) nutzt PL/SQL zurErstellung von Web-Applikationen)

• generell nichts Schlechtes daran!

• kritisch, Objekte müssen sich genau kennenKomponentenbasierte Software-

Entwicklung

Page 3: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

571

Ausblick auf weitere Themen

Komponentenbasierte Software-Entwicklung

Browser

Datenbank

JPA

EJBBean

Validation

CDIScope

JSFRESTful

WebService

Web Sockets

21

3

Page 4: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

572

Dependency Injection klassisch (1/2)

woher kommen Objekte für Exemplarvariablen?

• Variante 1: Werte werden als Parameter übergeben, aus denen Objekte gebaut werden (Objekt baut sich benötigte Objekte selber)

• Variante 2: Objekte werden als Referenzen übergeben

– Optimierung: Typen der Objektvariablen sind Interfaces; so konkrete Objekte leicht austauschbar

• Variante 2 heißt Dependency Injection mit get- und set-Methoden oder über Konstruktoren

Komponentenbasierte Software-Entwicklung

Page 5: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

573

Dependency Injection klassisch (2/2)

Nutzer nutzer = new Nutzer(new Inter1RealA(42)

, new Inter2RealC(43)

, new Inter3RealD("Hallo"));

eng verknüpft mit Factory Pattern

Komponentenbasierte Software-Entwicklung

Page 6: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

574

JSF nutzt bereits Dependency Injection

@Named

@SessionScoped

public class SprintController implements Serializable

@Inject

PersistenzService pers;

• @Named: Objekt steht und festen Namen zur Oberflächengestaltung zur Verfügung

• @SessionScoped: Objekt steht für die gesamte Session (auch allen anderen Objekten) zur Verfügung (Context)

• @Inject: „Umgebung gib (injiziere) mir ein zum Typen passendes Objekt“

• @PostConstruct: garantiert nach Erzeugung, vor Nutzung

• Hinweis: Annotationen stammen aus dem CDI-Paket; es gibt sehr ähnliche in JSF-Paketen (JSF ohne CDI machbar)

Komponentenbasierte Software-Entwicklung

Page 7: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

575

Ziele CDI

• Entkopplung von Objekten voneinander

– @Inject bestes Beispiel, es wird nur ein passendes Objekt „irgendwoher“ benötigt; dies besorgt CDI-Realisierung

• Vereinfachte Objekt-Kommunikation

– Beispiel: Informationen abonnieren (bekannt als PublishSubscribe oder Observer Observable)

• Vereinfachung von querschnittlich in mehreren Objekten benötigter Funktionalität

– Beispiel: Logging

• Hinzufügen von Funktionalität zu bestimmten Ereignissen ohne betroffene Methoden zu verändern

– Beispiel: Konsistenzprüfung, Benachrichtigung (Aspektorientierung)

Komponentenbasierte Software-Entwicklung

Page 8: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

576

Informationsquellen

• CDI 1.1 gehört zu JEE 7

• JSR 299: Contexts and Dependency Injection for the JavaTM EE platform, https://jcp.org/en/jsr/detail?id=299

• JSR 346: Contexts and Dependency Injection for JavaTM EE 1.1, https://jcp.org/en/jsr/detail?id=346

• JSR 365: Contexts and Dependency Injection for JavaTM 2.0 (Draft)

• Spezifikation http://www.cdi-spec.org/

– http://docs.jboss.org/cdi/spec/1.1/cdi-spec.pdf

– http://docs.jboss.org/cdi/spec/1.2/cdi-spec-1.2.pdf

• Referenzimplementierung Weld 2.0 (JBoss)

• gute Einführung: http://docs.jboss.org/weld/reference/latest/en-US/html/intro.html

Komponentenbasierte Software-Entwicklung

Page 9: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

577

NetBeans: kein Deploy on Save

gerade bei CDI ist ein vollständiges Clean & Build mit Deployfast immer sinnvoll, da Server sonst Probleme z. B. mit noch laufenden Sessions hat

Komponentenbasierte Software-Entwicklung

Page 10: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

578

Aktivierung

• explizit mit beans.xml in WEB-INF –Ordner; für reine EJB-Module oder jar-Dateien im Ordner META-INF<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee

http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"

version="1.1" bean-discovery-mode="all">

</beans>

• implizit, ohne beans.xml oder mit und bean-discovery-mode="annotated", werden nur Beans mit Scope gefunden; typischerweise @Dependent für im Scope des Nutzers

• in beans.xml können (und müssen teilweise) weitere Eigenschaften spezifiziert werden

Komponentenbasierte Software-Entwicklung

Page 11: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

579

zentrales Hilfsmittel Qualifier

• Qualifier sind einfache Annotationen, mit denen gewünschte bzw. geforderte Eigenschaften spezifiziert werden können

• Normale neue Annotation mit Zusatzannotation @Qualifier...

import javax.inject.Qualifier;

@Qualifier

@Target({ElementType.TYPE, ElementType.METHOD,

ElementType.PARAMETER, ElementType.FIELD})

@Retention(RetentionPolicy.RUNTIME)

public @interface Info{}

• folgende Folien: Qualifier nur erwähnt, haben dann die hier angegebene Form

Komponentenbasierte Software-Entwicklung

Page 12: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

580

Event-Model (Observer – Observable)

• auch Publish-Subscribe

• Observer sagt Bescheid, dass er vom Observable informiert werden möchte

• Observable schickt Informationen an alle Abonnenten

• Beispielaufgabe (Balkon): Informiere alle Interessierten, dass gerade ein Objekt persistiert werden soll

Komponentenbasierte Software-Entwicklung

Page 13: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

581

Event Model Übersicht (müssen nicht EJBs sein)

Komponentenbasierte Software-Entwicklung

class MeinEvent

beliebige POJO-Klasse

@Stateless

public class PersistenceService {

@Inject @Info Event<MeinEvent> event

MeinEvent me = …

event.fire(me);

Observable

@Qualifier

public @interface Info{}

Qualifier

@Stateless

public class EventConsumer {

public void empfangeMeinEvent(

@Observes @Info MeinEvent event)

{…

Observer

Page 14: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

582

Definition des Event-Objekts

• POJO mit Inhalten, die übertragen werden sollenpackage cdi.eventing;

public class MeinEvent { // POJO

private Object obj;

public MeinEvent(){

}

public Object getObj() {

return obj;

}

public void setObj(Object obj) {

this.obj = obj;

}

}

Komponentenbasierte Software-Entwicklung

Page 15: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

583

Observable – Benachrichtigen (Ausschnitt)

@Stateless

public class PersistenzService {

@Inject @Info Event<MeinEvent> event;

@Inject

private EntityManager em;

public void persist(Object object) {

MeinEvent e = new MeinEvent();

e.setObj(object);

event.fire(e);

em.persist(object);

}

Komponentenbasierte Software-Entwicklung

Page 16: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

584

Observer 1

• Durch Annotation @Info können verschiedenartige Events unterschieden werden

• beteiligte Objekte sind EJBs oder haben einen Scope (oder übernehmen Scope des nutzenden Objekts)@Stateless

public class EventConsumer {

public void empfangeMeinEvent(

@Observes @Info MeinEvent event) {

System.out.println(event.getObj());

}

}

// wenn Konsument nicht existiert, wird er erzeugt!

// nicht gewünscht: @Observes(notifyObserver=Recption.IF_EXISTS)

Komponentenbasierte Software-Entwicklung

Page 17: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

585

Observer 2

@Stateless

public class EventConsumer2 {

// Methode zeigt Machbarkeit des Ansatzes, ob dies hier

// sinnvoll, ist fraglich

public void empfangeMeinEvent(

@Observes @Info MeinEvent event) {

System.out.println(event.getObj().getClass());

if (event.getObj() instanceof Mitarbeit){

Mitarbeit m = (Mitarbeit)event.getObj();

if (m.getTaetigkeit().isEmpty()){

m.setTaetigkeit("intern");

}

}

}

}Komponentenbasierte Software-

Entwicklung

Page 18: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

586

Beispiel: neue Mitarbeit persistieren

INFO: Mitarbeit [id=0, version=0, geplanteStunden=8,

verbrauchteStunden=0, fertigstellungsgrad=0]

INFO: class entity.Mitarbeit

Komponentenbasierte Software-Entwicklung

Page 19: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

587

Konkretisierung injizierter Objekte

• bisher war immer eindeutig, welches Objekt bei @Inject genutzt wird

• häufig wird aber eine bestimmte Variante eines Objekts benötigt

• Ausgangspunkt: gibt Interface (oder abstrakte Klasse) mit mehreren Realisierungen

• der konkret gewünschte Objekttyp wird dann durch @Inject und die zusätzliche Angabe von Qualifiern festgelegt

• Beispiel: es gibt zwei verschiedene Ausgabemöglichkeiten, unterschieden durch Qualifier @LogQualifier und @SystemQualifier

Komponentenbasierte Software-Entwicklung

Page 20: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

588

Konkretisierung Übersicht

Komponentenbasierte Software-Entwicklung

interface Ausgabe {…

Angabe gewünschter Variante

@LogQualifier

public class AusgabeLog implements Ausgabe {…

@Qualifier

public @interface SystemQualifier{}

Qualifier

@Stateless

public class EventConsumer {

@Inject @LogQualifier Ausgabe aus;

@Qualifier

public @interface LogQualifier{}

Qualifier

@SystemQualifier

public class AusgabeSys implements Ausgabe {…

Interface

Realisierung

Realisierung

Page 21: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

589

Beispiel (1/4): Realisierungen 1/2

public interface Ausgabe {

public void ausgeben(String s);

}

@SystemQualifier

public class AusgabeSystem implements Ausgabe{

@Override

public void ausgeben(String s) {

System.out.println(s);

}

}

Komponentenbasierte Software-Entwicklung

Page 22: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

590

Beispiel (2/4): Realisierungen 2/2

@LogQualifier

public class AusgabeLog implements Ausgabe{

private final static Logger LOGGER = Logger

.getLogger(AusgabeLog.class.getSimpleName());

@Override

public void ausgeben(String s) {

LOGGER.log(Level.INFO, "AusgabeLog: {0}", s);

}

}

Komponentenbasierte Software-Entwicklung

Page 23: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

591

Beispiel (3/4): Auswahl der Realisierung

@Stateless

public class EventConsumer {

@Inject @LogQualifier Ausgabe aus;

public void empfangeMeinEvent(

@Observes @Info MeinEvent event) {

//System.out.println(event.getObj());

aus.ausgeben(event.getObj().toString());

}

}

• ein zentrales Logging kann man mit CDI besser durch Interceptors realisieren

• es können auch mehrere Qualifier angegeben werdenKomponentenbasierte Software-

Entwicklung

Page 24: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

592

Beispiel (4/4): Nutzung

INFO: AusgabeLog: (0) CDI einbauen

INFO: class entity.Sprint

Komponentenbasierte Software-Entwicklung

Page 25: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

593

Auswahlregeln

• Wenn Bean keinen Qualifier hat, wird er automatisch als @Default gesetzt (kann man auch hinschreiben)

• ohne benötigten Qualifier kann @Any genutzt werden

• Klassen haben ohne Scope-Angabe den Scope @Dependent, der sich dem Scope des nutzenden Objekts anpasst

Komponentenbasierte Software-Entwicklung

Page 26: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

594

Produzenten

• bisher wurde bei @Inject nach passenden Klassen gesucht und ein Objekt per Default-Konstruktor erzeugt

• Objekt-Erzeugung kann aber auch durch mit @Producesannotierte Konstruktoren, Methoden (Rückgabe-Objekt) oder direkt Exemplarvariablen erfolgen

• Konkretisierung des erzeugten Objekts wieder durch Qualifier (@Starttext, @Meldung im nächsten Beispiel)

• Beispiel zeigt kritische „Wiederverwendung“ von Qualifier

• javax.enterprise.inject.Produces nutzen

Komponentenbasierte Software-Entwicklung

Page 27: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

595

Statische Produzenten Übersicht (public vergessen)

Komponentenbasierte Software-Entwicklung

Produktions-varianten

@Qualifier

@interface Info{}

Qualifier

class Produzent {

@Produces @Meldung

private String meldung;

@Produces @Starttext

public String getLogtext() {…

@Produces @Starttext @Info

public String getLogtext2() {…

@Qualifier

@interface Meldung{}

Qualifier

class AusgabeLog {…

@Inject @Starttext @Info

private String start;

@Inject @Meldung

private String text;

Beispielnutzungen

@Qualifier

@interface Starttext{}

Qualifier

Page 28: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

596

Beispiel (1/3): Produzenten-Klasse

public class Produzent implements Serializable {

private String logtext = "logtext";

@Produces @Meldung

private String meldung;

public Produzent() { this.meldung = "Hai";}

@Produces @Starttext

public String getLogtext() {

return this.logtext;

}

@Produces @Starttext @Info

public String getLogtext2() {

System.out.println("getLogtext2");

return "2: " + this.logtext;

}

}

Komponentenbasierte Software-Entwicklung

Page 29: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

597

Beispiel (2/3): Nutzer der Produzenten

@LogQualifier

public class AusgabeLog implements Ausgabe{

private final static Logger LOGGER = Logger

.getLogger(AusgabeLog.class.getSimpleName());

@Inject @Starttext @Info private String start;

@Inject @Meldung private String text;

@Override

public void ausgeben(String s) {

//LOGGER.log(Level.INFO, "AusgabeLog: {0}", s);

LOGGER.log(Level.INFO, "{0} {1}: {2}"

, new Object[]{this.text, this.start, s});

}

}Komponentenbasierte Software-Entwicklung

Page 30: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

598

Beispiel (3/3): Beispielnutzung

INFO: getLogtext2

INFO: Hai 2: logtext: (0) Qualifier überlegen

INFO: class entity.BacklogElement

Komponentenbasierte Software-Entwicklung

Page 31: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

599

Dynamische Produzenten Übersicht

Komponentenbasierte Software-Entwicklung

Produktions-methode

Qualifier

public class Produzent{

@Produces @Aktuell

public String mach(){…

@Qualifier

public @interface Aktuell{}

public class AusgabeLog {

@Inject @Aktuell

Instance<String> datum;

public void ausgeben(…) {

datum.get()});

Beispielnutzung

Page 32: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

600

Dynamische Produktion (1/3) : Erzeugung

• wieder Produzenten-Methode mit üblichen Qualifier (also nichts Neues hier)

public class Produzent implements Serializable {

@Produces @Aktuell

public String mach(){

return new Date().toString();

}

...

Komponentenbasierte Software-Entwicklung

Page 33: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

601

Dynamische Produktion (2/3): Aufruf

@LogQualifier

public class AusgabeLog implements Ausgabe{

@Inject @Aktuell Instance<String> datum;

...

@Override

public void ausgeben(String s) {

LOGGER.log(Level.INFO, "AusgabeLog: {0} - {1}"

, new Object[]{s, datum.get()});

// LOGGER.log(Level.INFO, "{0} {1}: {2}"

// , new Object[]{this.text, this.start, s});

}

Komponentenbasierte Software-Entwicklung

Page 34: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

602

Dynamische Produktion (3/3): Beispielnutzung

INFO: AusgabeLog: (14) Fernando Alonso - Wed May 21 20:15:42 CEST 2014

INFO: AusgabeLog: (7) Kimi Räikkönen - Wed May 21 20:14:24 CEST 2014

Komponentenbasierte Software-Entwicklung

Page 35: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

603

Inject-Varianten

• statt @Inject an Exemplarvariablen zu schreiben, ist dies auch möglich:@Inject

public Konstruktor(Typ ichWerdeInjected){ …

@Inject

public void methode(Typ ichWerdeInjected){ …

• natürlich wieder Qualifier nutzbar

• weiterführend: mit @Typed an Klasse einschränken, für welche Klassen und Interfaces diese eingesetzt werden kann

Komponentenbasierte Software-Entwicklung

Page 36: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

604

Alternativen

• über Qualifier können passende Klassen genau ausgewählt werden

• z. B. zu Testzwecken, sollte diese Auswahl aber einfach änderbar sein

– hierzu wird Klasse mit @Alternative markiert

– UND muss in der beans.xml als ausgewählte Alternative angegeben werden

• durch Änderung der beans.xml sehr einfach Klassenauswahl auf Testphase oder länderspezifische Auswahlen änderbar

• mehrere Alternativen bei mehreren genutzten jars angebbar, dann Auswahl so steuerbar:

@Priority(Interceptor.Priority.APPLICATION + 10)

komplexes, sehr flexibles Auswahlsystem, wann welche Klasse genutzt wird (@Specialization)

Komponentenbasierte Software-Entwicklung

Page 37: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

605

Nutzung der Alternative (1/3): weitere Klasse

import cdi.qualifier.ausgabe.LogQualifier;

import javax.enterprise.inject.Alternative;

@Alternative

@LogQualifier

public class AusgabeLogMock implements Ausgabe{

@Override

public void ausgeben(String s) {

System.out.println("LogMock: " + s );

}

}

Komponentenbasierte Software-Entwicklung

Page 38: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

606

Nutzung der Alternative (2/3): bean.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee

http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"

bean-discovery-mode="all">

<alternatives>

<class>cdi.AusgabeLogMock</class>

</alternatives>

</beans>

Komponentenbasierte Software-Entwicklung

Page 39: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

607

Nutzung der Alternative (3/3): Nutzung

INFO: LogMock: (0) Alternativen realisieren

INFO: class entity.BacklogElement

Komponentenbasierte Software-Entwicklung

Page 40: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

608

Interceptor Übersicht

Komponentenbasierte Software-Entwicklung

unterbreche alle Methoden von

Interceptor-Benennung

@Stateless

@InterceptQualifier

public class BspKlasse {

public void meth1(…) {…

public void meth2(…) {…

@Inherited

@InterceptorBinding

public @interface InterceptQualifier{}

@InterceptQualifier

@Interceptor

public class MeinInterceptor {

@AroundInvoke

public Object logCall(

InvocationContext ctx)

throws Exception { …

Method meth = ctx.getMethod();

for (Object o: ctx.getParameters())

return ctx.proceed();

} …

bei Unterbrechung zu nutzen

<interceptors>

<class>cdi.MeinInterceptor

</class>

</interceptors>

Page 41: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

609

Interception

• Ansatz: sich in verschiedenen Methoden wiederholende Aufgaben zentral auslagern (Aspekt-Orientierung)

• (einziger) Klassiker: Logging

• Ansatz: Werden markierte Methoden oder Methoden in markierten Klassen ausgeführt, wird zunächst zum Interceptor gehörende Methode durchgeführt

• Interceptor kann auf Methode und Parameter zugreifen

• Interceptor muss Methodenausführung starten (proceed())

• Interceptor muss über bean.xml eingeschaltet werden (nur in diesem Archiv aktiv) oder @Priority-Annotation besitzen

• Interceptor benötigt eigene Art von Qualifier

• folgendes Beispiel zeigt ungewöhnliche Nutzung (auch Verstoß, dass möglichst wenig beobachtet werden soll)

Komponentenbasierte Software-Entwicklung

Page 42: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

610

Nutzung von Interception (1/5): Annotation

import java.lang.annotation.ElementType;

import java.lang.annotation.Inherited;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

import javax.interceptor.InterceptorBinding;

//@Qualifier

@Inherited

@InterceptorBinding

@Target({ElementType.TYPE, ElementType.METHOD })

@Retention(RetentionPolicy.RUNTIME)

public @interface InterceptQualifier{}

Komponentenbasierte Software-Entwicklung

Page 43: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

611

Nutzung von Interception (2/5): Bereich festlegen

• Hier werden alle Methoden der Klasse beobachtet, man kann die Annotation auch nur für einzelne Methoden nutzen

@Stateless

@InterceptQualifier

public class EventConsumer2 {

public void empfangeMeinEvent(

@Observes @Info MeinEvent event) {

System.out.println(event.getObj().getClass());

if (event.getObj() instanceof Mitarbeit){

Mitarbeit m = (Mitarbeit)event.getObj();

if (m.getTaetigkeit().isEmpty()){

m.setTaetigkeit("intern");

}

}

}

}

Komponentenbasierte Software-Entwicklung

Page 44: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

612

Nutzung von Interception (3/5): Realisierung 1/2

@InterceptQualifier

@Interceptor

public class MeinInterceptor {

@AroundInvoke // gibt auch @AroundConstruct, @PostConstruct

public Object logCall(InvocationContext context)

throws Exception {

Method meth = context.getMethod();

System.out.println("Methode: " + meth);

/*

for (Object o : context.getParameters()) {

System.out.print(o + " ");

}

*/Komponentenbasierte Software-

Entwicklung

Page 45: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

613

Nutzung von Interception (4/5): Realisierung 2/2

MeinEvent event = (MeinEvent) context.getParameters()[0];

if (event.getObj() instanceof Mitarbeiter) {

Mitarbeiter m = (Mitarbeiter) event.getObj();

if (m.getMinr() == 999) {

m.setMinr((int) (100000 + System.nanoTime()%900000));

// m.setMinr((int) m.getId()); kann nicht gehen, da 0

}

}

return context.proceed(); // wichtig irgendwann aufrufen

}

}

Komponentenbasierte Software-Entwicklung

Page 46: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

614

Nutzung von Interception (3/4): beans.xml

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee

http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"

bean-discovery-mode="all">

<interceptors>

<class>cdi.MeinInterceptor</class>

</interceptors>

</beans>

Komponentenbasierte Software-Entwicklung

Page 47: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

615

Nutzung von Interception (4/4): Nutzung

INFO: getLogtext2

INFO: Hai 2: logtext: (999) Clark Kent

INFO: Methode: public void

cdi.eventing.EventConsumer2.empfangeMeinEvent(cdi.eventing.

MeinEvent)

INFO: class entity.Mitarbeiter

Komponentenbasierte Software-Entwicklung

Page 48: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

616

Stereotype

• mit CDI können große Mengen von Annotationen entstehen

• häufiger haben ähnliche Klassen die gleichen Annotationen

• diese können als neue Annotation zusammengefasst werden

@RequestScoped

@Named

@MeineAnnotation

@Stereotype

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

public @interface Aktion {}

• Klassen können auch mit mehreren Stereotypes (auch überlappend) annotiert werden

• Beispiel: @Model vereint @Named und @RequestScopedKomponentenbasierte Software-

Entwicklung

Page 49: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

617

Weiterführende Themen

• @Decorator, verwandt mit @Interceptor, ermöglicht Ergänzung von Funktionalität zu bestimmten Methoden

• CDI auch zu eigener Transaktionssteuerung nutzbar

Meinung: wenn JEE und EJB genutzt werden, spricht wenig für diesen Ansatz (Transaktion über mehrere Methoden)

interessant:

[Mül 14] B. Müller, JSF und JPA im Tandem, Teil 1, in: Javamagazin, 5/2014, Seiten 98-102, Software & Support Media GmbH, Frankfurt a. M. , 2014

• Auf Spezifikationsseite kann man sich über Version 1.2 informieren

Komponentenbasierte Software-Entwicklung

Page 50: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

618

Fazit

• CDI ermöglicht eine sehr große Entkopplung der Klassen voneinander

• Klassen werden so flexibler einsetzbar, evtl. Programmiermodel intuitiver

• im Beispiel wird „Balkon“ an Projekt programmiert, da @Inject und @...Scope ausreichen; nicht untypisch für klassisches JEE-Projekt

• CDI macht SW zur Zeit noch langsamer

• Annotations-Warfare-Area wird drastisch vergrößert

Komponentenbasierte Software-Entwicklung

Page 51: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

619

7. (RESTful) Web Services

• JavaScript Object Notation

• JSONP

• Idee: Web-Services

• Idee: RESTful

• erste Services

• GET, POST

• Clients

• Response

• Path-Parameter

• Aufrufparameter

• Architektur von REST-Applikationen

• Fallstudie (GET, POST, PUT, DELETE)

• Ausblick

Komponentenbasierte Software-Entwicklung

Page 52: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

620

Ausblick auf weitere Themen

Komponentenbasierte Software-Entwicklung

Browser

Datenbank

JPA

EJBBean

Validation

CDIScope

JSFRESTful

WebService

Web Sockets

21

3

Page 53: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

621

Einstieg JSON

• JavaScript Object Notation (http://json.org/)

• textuelles Austauschformat, abgeleitet aus JavaScript{ "name": "Tony Stark",

"alter": 42,

"firma": { "name": "Stark Industries",

"ort": "New York, N.Y"

},

"freunde":["Steve Rogers", "Bruce Banner"]

}

• Sammlung von

– (Name: Wert)-Paaren

– Arrays von Werten

• Werte können wieder aus beiden Elementen bestehen

Komponentenbasierte Software-Entwicklung

Page 54: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

622

Vereinheitlichung von JSON in Java

in JEE 7 ergänzt:

• JSR 353: JavaTM API for JSON Processing (23.5.2013), https://jcp.org/en/jsr/detail?id=353

• Referenzimplementierung jsonp https://jsonp.java.net/

• in Glassfish seit 4.0 enthalten

zwei zentrale APIs

• Object Model API; sehr analog zum DOM API für XML parsing

• Streaming API; sehr analog zum StAX API

• unabhängig von Programmiersprachen nutzbar

• kompakter als XML (ähnlich gut/schlecht menschenlesbar)

Komponentenbasierte Software-Entwicklung

Page 55: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

623

Beispiel: JSON-Object lesen (1/2)

public static void main(String[] args) {

String daten =

"{ \"name\": \"Tony Stark\","

+ " \"alter\": 42,"

+ " \"firma\": { \"name\": \"Stark Industries\","

+ " \"ort\": \"New York, N.Y\""

+ "},"

+ "\"freunde\":[\"Steve Rogers\", \"Bruce Banner\", 42]"

+ "}";

JsonReader reader = Json.createReader(new StringReader(daten));

JsonObject tony = reader.readObject();

reader.close();

//Set<String> namen = tony.keySet(); // geht auch

Komponentenbasierte Software-Entwicklung

Page 56: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

624

Beispiel: JSON-Objekt lesen (2/2)

System.out.println("Name : " + tony.getString("name"));

System.out.println("Alter : " + tony.getInt("alter"));

JsonObject firma = tony.getJsonObject("firma");

System.out.println("Firmenname : " + firma.getString("name"));

System.out.println("Umsatz : " + firma.getInt("umsatz", 20));

JsonArray freunde = tony.getJsonArray("freunde");

for (JsonValue freund : freunde) {

System.out.println(freund + " * " + freund.getValueType());

}

}

Name : Tony Stark

Alter : 42

Firmenname : Stark Industries

Umsatz : 20

Steve Rogers * STRING

Bruce Banner * STRING

42 * NUMBER

Default, wenn nicht da

Komponentenbasierte Software-Entwicklung

Page 57: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

625

Beispiel: JSON-Objekt von Hand erstellen

public static void main(String[] args) {

JsonObject personObject = Json.createObjectBuilder()

.add("name", "Bruce Banner")

.add("alter", 44)

.add("firma",

Json.createObjectBuilder()

.add("name", "Shield")

.add("ort", "unbekannt")

.build())

.add("freunde",

Json.createArrayBuilder()

.add("James Howlett")

.add("Ben Grimm")

.build())

.build();

System.out.println("Object: " + personObject);

}

Object:

{"name":"Bruce

Banner","alter":44,"f

irma":{"name":"Shield

","ort":"unbekannt"},

"freunde":["James

Howlett","Ben

Grimm"]}

Komponentenbasierte Software-Entwicklung

Page 58: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

626

Ausschnitt Klassendiagramm

Komponentenbasierte Software-Entwicklung

Page 59: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

627

Beispiel: Stream-Bearbeitung von JSON

// daten: siehe JSON lesen

JsonParser parser = Json

.createParser(new StringReader(daten));

while (parser.hasNext()) {

Event event = parser.next();

System.out.print(event + ": ");

switch (event) {

case KEY_NAME:

System.out.print(parser.getString());

break;

case VALUE_NUMBER:

System.out.print(parser.getInt());

break;

}

System.out.println("");

}

START_OBJECT:

KEY_NAME: name

VALUE_STRING:

KEY_NAME: alter

VALUE_NUMBER: 42

KEY_NAME: firma

START_OBJECT:

KEY_NAME: name

VALUE_STRING:

KEY_NAME: ort

VALUE_STRING:

END_OBJECT:

KEY_NAME: freunde

START_ARRAY:

VALUE_STRING:

VALUE_STRING:

VALUE_NUMBER: 42

END_ARRAY:

END_OBJECT:Komponentenbasierte Software-Entwicklung

Page 60: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

628

Binding

• Binding schafft automatische Umwandlungsmöglichkeit von A nach B und von B nach A

• ohne Binding muss die Umwandlung (marshalling) manuell erfolgen, bei Netztransport ggfls. Rückumwandlung notwendig (unmarshalling)

• Java-Objekt von und nach XML löst JAXB

• JSR 222: JavaTM Architecture for XML Binding (JAXB) 2.0, https://jcp.org/en/jsr/detail?id=222

• wichtig Umwandlungsprozess konfigurierbar

• Java-Objekt von und nach JSON noch nicht standardisiert (für JEE 8 angekündigt)

• Referenzimplementierung für Glassfish (Stand Ende 2013) ist MOXy (übersetzt JAXB-Annotationen nach JSON)

Komponentenbasierte Software-Entwicklung

Page 61: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

629

Beispiel: Vorbereitung einer Entitäts-Klasse für JSON

@XmlRootElement

public class Punkt implements Serializable {

private int x;

private int y;

public Punkt() {} // wichtig

public Punkt(int x, int y) {this.x = x; this.y = y;}

public int getX() {return x;}

public int getY() {return y;}

public void setX(int x) {this.x = x;}

public void setY(int y) {this.y = y;}

@Override

public String toString() {return "[" + x + "," + y + "]";}

}

Komponentenbasierte Software-Entwicklung

Page 62: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

630

Annotationen zur Steuerung der Übersetzung

@XmlElement(name=“rufname") // Key-Umbenennung

public String name;

@XmlTransient // nicht übertragen

public int alter;

• man beachte, dass man erhaltenes Objekt auch noch mit vorherigen Methoden modifizieren kann

• Übersetzung noch nicht standardisiert (aktuell MOXy, Teil von EclipseLink)

• da manuelle JsonObject-Erzeugung nicht sehr aufwändig und sehr flexibel, wird es gute Alternative bleiben

Komponentenbasierte Software-Entwicklung

Page 63: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

631

Hintergrund Web Services

• zentraler Wunsch: einfache Nutzung von Software über das Netz

• unabhängig wo sich ein Rechner befindet

• unabhängig von der Programmiersprache

SOAP-basierte WebServices

• jeder Service hat eindeutige Kennung (URI, Uniform Resource Identifier)

• Schnittstellenbeschreibung WSDL

• typisch: XML-basierte Kommunikationsprotokolle

• typisch: Verbindung mit SOA

• hier nicht wichtig, aber SOA ≠ SOAP ≠ Web Service

Komponentenbasierte Software-Entwicklung

Page 64: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

632

Hintergrund: Service Oriented Architecture

Service-

Verzeichnis

Service-

Anbieter

Service-

Nutzer

3. Anfragen

4. Antworten

SOAP

WSDL

HTTP

UDDI

Komponentenbasierte Software-Entwicklung

Page 65: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

633

Zwischenfazit SOA

• Vision: auf Grundlage von Geschäftsprozessmodellierungen kann individuelle Software für ein Unternehmen entstehen

• Realität: machbar, wenn alles auf einem Hersteller basiert

• Realität: UDDI hat in fast allen Projekten nicht stattgefunden (SOA ist auch Super Overhyped Acronym)

• aber: WebServices basierend auf SOAP haben als Kommunikationskonzept zentrale Bedeutung bekommen

• gilt als relativ langsam

• aber: Unternehmen nutzen es um MS-basierte Oberfläche mit JEE-realisiertem Server zu verbinden

Komponentenbasierte Software-Entwicklung

Page 66: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

634

RESTful (Representational State Transfer)

• Idee von der Interaktion zwischen Rechnern bleibt

• REST ist ein Architekturstil für verteilte Hypermedia-Systeme

• Protokoll: nutze Möglichkeiten von HTTP

– GET: lese Information (SELECT)

– POST: neue Information (INSERT)

– PUT: ändere Information (UPDATE)

– DELETE: lösche Information (DELETE)

• Klammern deuten Ähnlichkeit zu Datenbankoperationen an

• Grundlage: Dissertation Roy Fielding „Architectural Styles and the Design of Network-based Software Architectures “

• http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm

Komponentenbasierte Software-Entwicklung

Page 67: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

635

Woher kommt „ Representational State Transfer“

Client fordert Information mit Hilfe einer URL an.

Eine Repräsentation der Information wird als Ergebnis zurückgegeben (z. B. in Form eines JSON-Objekts), Client hat Informationszustand.

Client nutzt Hyperlink in Ergebnis um weitere Informationen anzufordern.

Neues Ergebnis versetzt Client in einen neuen Informationszustand.

ResourceClient

http://www.scrumsprinter.de/sprint/42

{ “id”: 42,

“name”: “Prototyp”,

“elemente”: [ …

Komponentenbasierte Software-Entwicklung

Page 68: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

636

HATEOAS – saubere REST-Architektur

„Hypermedia as the Engine of Application State“

• Client kennt nur die Basis-URI des Dienstes

• Server leitet durch Informationszustände der Anwendung durch Bekanntgabe von Wahlmöglichkeiten (Hyperlinks)

• Der vollständige Informationszustand kann beim Client oder beim Server liegen, oder auch über beide verteilt sein

• HTTP-Kommunikationsprotokoll selbst bleibt zustandslos

• Grundregel: GET, PUT, DELETE sind idempotent; führen zum gleichen Ergebnis, egal wie oft sie im gleichen Informationszustand aufgerufen werden

• häufig genutzter Trick: POST auch zur partiellen Aktualisierung

Komponentenbasierte Software-Entwicklung

Page 69: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

637

Wer nutzt es (Beispiele)?

• Hinweis: Öfter wird gegen die geforderte Reinform von RESTful WebServices verstoßen, und normale Anfragemöglichkeit mit GET als RESTful bezeichnet

• Google Maps

• Google AJAX Search API

• Yahoo Search API

• Amazon WebServices

Komponentenbasierte Software-Entwicklung

Page 70: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

638

Standardisierung in Java

viele Implementierungen

• Restlet http://www.restlet.org/

• Apache CXF http://cxf.apache.org/

• Project Zero http://www.projectzero.org

• GlassFish Jersey https://jersey.dev.java.net/ (Referenz)

• JBoss RESTeasy http://www.jboss.org/resteasy/

Standardisierung für Java:

• JSR 311: JAX-RS: The JavaTM API for RESTful Web Services, https://jcp.org/en/jsr/detail?id=311 (10.10.2008)

• JSR 339: JAX-RS 2.0: The Java API for RESTful Web Services, https://jcp.org/en/jsr/detail?id=339 (24.5.2013)

Komponentenbasierte Software-Entwicklung

Page 71: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

639

JAX-RS aktivieren

• in JEE-aware Servern reicht theoretisch folgendes ausimport javax.ws.rs.ApplicationPath;

import javax.ws.rs.core.Application;

@ApplicationPath("resources")

public class ApplicationConfig extends Application {

}

• ist generell im .war-File

• sonst Konfiguration als Servlet nötig

• Beschreibung in web.xml

Komponentenbasierte Software-Entwicklung

Page 72: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

640

JAX-RS aktivieren (Alternative)

@ApplicationPath("resources")

public class ApplicationConfig extends Application {

@Override

public Set<Class<?>> getClasses() {

Set<Class<?>> resources = new java.util.HashSet<>();

try { // customize Jersey 2.0 JSON provider:

Class jsonProvider = Class

.forName("org.glassfish.jersey.moxy.json.MoxyJsonFeature");

resources.add(jsonProvider);

} catch (ClassNotFoundException ex) {}

addRestResourceClasses(resources);

return resources;

}

private void addRestResourceClasses(Set<Class<?>> resources) {

resources.add(hello.HelloWorld.class);

}

}

Anbieter von Services

Komponentenbasierte Software-Entwicklung

Page 73: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

641

erste RESTful-WebServices

@Path("/helloworld")

public class HelloWorld {

public HelloWorld() { }

@GET

@Produces("text/html")

public String getHtml() {

return "<html><body><h1>Hello, World!!</h1></body></html>";

}

@GET

@Produces(MediaType.TEXT_PLAIN)

public String getText() {

return "Tach Welt";

}

}Komponentenbasierte Software-Entwicklung

Page 74: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

642

detaillierte Analyse@Path("/helloworld")

• Gibt Aufrufpfad an, hier resources/helloworld

• Pfad wird an Projektpfad, z. B. /vlRESTAnfang, angehängt

• könnte auch nur an einzelnen Methoden stehen

• kann auch zusätzlich an Methoden stehen, so dass sich der Pfad verlängert

@GET

@Produces("text/html")

• Annotationen aus javax.ws.rs

• HTTP-Befehl und Ergebnistyp (mögliche Ergebnistypen, mehrere MIME-Typen [Multipurpose Internet Mail Extension])

• nachfolgender Methodenname spielt keine Rolle!

Komponentenbasierte Software-Entwicklung

Page 75: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

643

direkter Aufruf

• bei GET ist direkter Aufruf im Browser möglich

• aber, das ist ein sehr sehr untypisches Szenario

• typisch:

– Aufruf direkt aus einer Web-Seite, meist mit JavaScript

– Aufruf aus anderer Software heraus mit Mitteln der jeweiligen Programmiersprache (z. B. java.net.URL)

• NetBeans: kein Haken bei „Display Browser on Run“

Komponentenbasierte Software-Entwicklung

Page 76: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

644

Detaillierte Analyse mit cURL

• generell jedes Programm zur Erzeugung von HTTP-Aufrufen und Analyse der Ergebnisse geeignet

• Kommando-Zeile mit cURLhttp://curl.haxx.se/download.html

• Für etwaige Parameter muss auch URL in Anführungsstrichen stehen

• viele Browser unterstützen direkt bei solchen Tests

Komponentenbasierte Software-Entwicklung

Page 77: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

645

Nutzung automatischen Marshallings - GET

• verschiedene Rückgabetypen bedienbar (praktisch sinnvoll?)@GET

@Produces({MediaType.TEXT_XML, MediaType.APPLICATION_JSON})

public Punkt getJSon2() {

return new Punkt(42,43); // war @XMLRootElement annotiert

}

Komponentenbasierte Software-Entwicklung

Page 78: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

646

Nutzung automatischen Unmarshallings - POST

@POST

@Produces(MediaType.TEXT_PLAIN)

@Consumes(MediaType.APPLICATION_JSON)

public String postit(Punkt p){

System.out.println(p);

return "ok";

}

• weitere Parameter im JSON-Objekt führen zu Fehlern

Komponentenbasierte Software-Entwicklung

Page 79: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

647

zentrale Klassen Client und Response

• RESTful Web Services werden typischerweise aus anderer Software aufgerufen

• dies ist natürlich auch in Java möglich; vor JAX-RS 2.0 aber proprietäre Lösungen der Anbieter

• https://jersey.java.net/download.html

• jetzt Klasse javax.ws.rs.client.Client

• Bei der Nutzung von RESTful Web Services können verschiedene Klassen als Typen für Parameter und Rückgabe genutzt werden

• Hilfreich ist Klasse javax.ws.rs.core.Response

• Server erzeugt Response-Objekt

• Client kann problemlos Response-Objekt lesen

• Response ist ein Stream, muss auch geschlossen werden

Komponentenbasierte Software-Entwicklung

Page 80: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

648

Hilfsmethode zur genaueren Analyse von Response

private void details(Response res) {

System.out.println("-----------------\n"

+ "AllowedMethods : " + res.getAllowedMethods() + "\n"

+ "Entity Class: " + res.getEntity().getClass() + "\n"

+ "Language : " + res.getLanguage() + "\n"

+ "Location : " + res.getLocation() + "\n"

+ "Mediatype : " + res.getMediaType() + "\n"

+ "Links : " + res.getLinks() + "\n"

+ "Status : " + res.getStatus() + "\n"

+ "Date : " + res.getDate() + "\n"

+ "Class : " + res.getClass() + "\n"

+ "Inhalt : " + res.readEntity(String.class));

res.close();

}

Komponentenbasierte Software-Entwicklung

Page 81: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

649

Kleine Beispiele (1/7)

• Anmerkung: Zeigt Service-Nutzung, zeigt nichts von RESTpublic class ClientAnalyse {

private Client client;

private WebTarget userTarget;

public ClientAnalyse() {

Client client = ClientBuilder.newClient();

userTarget = client

.target("http://localhost:8080/vlRESTAnfang"

+ "/resources/helloworld");

}

Komponentenbasierte Software-Entwicklung

Page 82: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

650

Kleine Beispiele (2/7)

public void analyse1() {

Response res = userTarget.request("text/html").get();

details(res);

}

AllowedMethods : []

Entity Class: class org.glassfish.jersey.client.HttpUrlConnector$2

Language : null

Location : null

Mediatype : text/html

Links : []

Status : 200

Date : Fri Dec 18 15:39:22 CET 2015

Class : class org.glassfish.jersey.client.InboundJaxrsResponse

Inhalt : <html lang="en"><body><h1>Hello, World!!</h1></body></html>

Komponentenbasierte Software-Entwicklung

Page 83: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

651

Kleine Beispiele (3/7)

public void analyse1() {

Response res = userTarget.request(MediaType.TEXT_PLAIN).get();

details(res);

}

AllowedMethods : []

Entity Class: class org.glassfish.jersey.client.HttpUrlConnector$2

Language : null

Location : null

Mediatype : text/plain

Links : []

Status : 200

Date : Wed May 14 18:55:35 CEST 2014

Class : class org.glassfish.jersey.client.ScopedJaxrsResponse

Inhalt : <html lang="en"><body><h1>Hello, World!!</h1></body></html>

Komponentenbasierte Software-Entwicklung

Page 84: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

652

Kleine Beispiele (4/7)

public void analyse3() {

Response res = userTarget

.request(MediaType.APPLICATION_JSON).get();

details(res);

}

AllowedMethods : []

Entity Class: class org.glassfish.jersey.client.HttpUrlConnector$1

Language : null

Location : null

Mediatype : application/json

Links : []

Status : 200

Date : Wed May 14 18:55:35 CEST 2014

Class : class org.glassfish.jersey.client.ScopedJaxrsResponse

Inhalt : {"x":42,"y":43}

Komponentenbasierte Software-Entwicklung

Page 85: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

653

Kleine Beispiele (5/7)

public void analyse4() {

Response res = userTarget.request(MediaType.TEXT_XML).get();

details(res);

}

AllowedMethods : []

Entity Class: class org.glassfish.jersey.client.HttpUrlConnector$1

Language : null

Location : null

Mediatype : text/xml

Links : []

Status : 200

Date : Wed May 14 19:08:13 CEST 2014

Class : class org.glassfish.jersey.client.ScopedJaxrsResponse

Inhalt : <?xml version="1.0" encoding="UTF-8"

standalone="yes"?><punkt><x>42</x><y>43</y></punkt>

Komponentenbasierte Software-Entwicklung

Page 86: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

654

Kleine Beispiele (6/7)

public void analyse5() {

Builder buil = this.userTarget.request(MediaType.TEXT_PLAIN);

Entity e = Entity.entity(new Punk(3, 4)

, MediaType.APPLICATION_JSON);

System.out.println(e + " : " + e.getEntity());

String res = buil.post(e, String.class);

System.out.println(res);

}

javax.ws.rs.client.Entity@52aa911c : [3,4]

ok

• Anmerkung: Klasse Punk wie Punkt, sogar ohne XMLRootElement-Annotation , aber Serializable

Komponentenbasierte Software-Entwicklung

Page 87: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

655

Kleine Beispiele (7/7)

public void analyse6() {

Builder buil = this.userTarget.request(MediaType.TEXT_PLAIN);

Entity e = Entity.json(new Punk(2,3));

System.out.println(e + " : " + e.getEntity());

String res = buil.post(e, String.class);

System.out.println(res);

}

Entity{entity=[2,3], variant=Variant[mediaType=application/json,

language=null, encoding=null], annotations=[]} : [2,3]

ok

• Klasse Entity bietet einige Marshalling-Methoden

Komponentenbasierte Software-Entwicklung

Page 88: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

656

flexible Dienststrukturen

• generell soll man aus Antworten auf weitere Abfragemöglichkeiten schließen können

• /helloworld/kunden/

Frage nach Kunden: Sammlung der Namen aller Kunden

• /helloworld/kunden/Hoeness/

Frage nach Kunden mit Namen: alle Eigenschaften des Kunden

• /helloworld/kunden/Hoeness/konten

Frage nach Konten eines benannten Kunden: Sammlung aller Konten des Kunden

• /helloworld/kunden/Hoeness/konten/42

Frage nach Kontonummer eines benannten Kunden: alle Eigenschaften des Kontos dieses Kunden

Komponentenbasierte Software-Entwicklung

Page 89: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

657

Beispiel: Umsetzung von Pfaden (1/4)

@Path("helloworld")

public class HelloWorld {

// Kundenname, Sammlung von Konten (Nummer, Betrag)

private Map<String, Map<Integer, Long> > kunden;

public HelloWorld() {

// zufaellige Beispieldaten

Map<Integer,Long> tmp = new HashMap<>();

tmp.put(42,32000000L);

kunden = new HashMap<>();

kunden.put("Hoeness", tmp);

}

Komponentenbasierte Software-Entwicklung

Page 90: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

658

Beispiel: Umsetzung von Pfaden (2/4)

@GET

@Produces(MediaType.APPLICATION_JSON)

@Path("/kunden/{user}/konten/{id}")

public JsonObject getKontostand(

@PathParam("user") String user

, @PathParam("id") int id) {

JsonObjectBuilder erg = Json.createObjectBuilder();

Map<Integer,Long> kunde = kunden.get(user);

if(kunde == null){

return erg.add("fehler", "kein Kunde").build();

}

Long summe = kunde.get(id);

if(summe == null){

return erg.add("fehler", "kein Konto").build();

}

return erg.add("summe", summe).build();

}Komponentenbasierte Software-

Entwicklung

Page 91: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

659

Beispiel: Umsetzung von Pfaden (3/4)

public static void main(String[] a){

String[] verdaechtig = {"Rummenigge", "Hoeness"};

int[] nummern = {42,43};

Client client = ClientBuilder.newClient();

for(String v:verdaechtig){

for (int n:nummern){

WebTarget target = client.target("http://localhost:8080"

+ "/vlRESTAnfang/resources/helloworld/kunden/"

+ v + "/konten/" + n);

JsonObject erg = target

.request(MediaType.APPLICATION_JSON)

.get(JsonObject.class);

System.out.println(erg);

}

}

}

Komponentenbasierte Software-Entwicklung

Page 92: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

660

Beispiel: Umsetzung von Pfaden (4/4)

{"fehler":"kein Kunde"}

{"fehler":"kein Kunde"}

{"summe":32000000}

{"fehler":"kein Konto"}

Komponentenbasierte Software-Entwicklung

Page 93: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

661

Umsetzung von Pfaden

@Path("/kunden/{user}/konten/{id}")

• Einbau von Pfadvariablen, auf die in Parameterliste mit @PathParam("user") zugegriffen werden kann

• einfache Java-Typen, typischerweise int, long, String nutzbar; Konvertierung automatisch

• Pfadvariablen in der Klassenannotation können dann in jedem Methodenkopf genutzt werden

• Pfadvariablen können in @Path doppelt vorkommen und müssen dann gleichen Wert bei Nutzung haben

• im Hinterkopf: wenn HTTPS, dann auch User-Token so übertrag- und später prüfbar (Sicherheit)

• im Hinterkopf: individueller Wert für jeden Nutzer, der E-Mail mit so einem Link erhält

Komponentenbasierte Software-Entwicklung

Page 94: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

662

Externer Service zur Analyse von IPs (1/4)

private static void zeigeJsonObjekt(JsonObject js){

for(String key:js.keySet()){

System.out.println(key+ ": " + js.get(key));

}

}

public static void main(String[] s){

String SERVICE = "http://freegeoip.net/json";

Client client = ClientBuilder.newClient();

WebTarget wt = client.target(SERVICE);

Invocation.Builder invoc = wt.request();

JsonObject ergebnis = invoc.get(JsonObject.class);

zeigeJsonObjekt(ergebnis);

zeigeJsonObjekt(client.target(SERVICE+"/www.bild.de")

.request().get(JsonObject.class));

}Komponentenbasierte Software-Entwicklung

Page 95: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

663

Externer Service zur Analyse von IPs (2/4)

ip: "84.155.86.93"

country_code: "DE"

country_name: "Germany"

region_code: "NI"

region_name: "Lower Saxony"

city: "Neuenkirchen"

zip_code: "49586"

time_zone: "Europe/Berlin"

latitude: 52.4167

longitude: 7.85

metro_code: 0

ip: "72.247.9.43"

country_code: "US"

country_name: "United States"

region_code: "MA"

region_name: "Massachusetts"

city: "Cambridge"

zip_code: "02142"

time_zone: "America/New_York"

latitude: 42.3626

longitude: -71.0843

metro_code: 506

Komponentenbasierte Software-Entwicklung

Page 96: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

664

Externer Service zur Analyse von IPs (3/4)

public static void main(String[] st){

Client client = ClientBuilder.newClient();

WebTarget wt = client.target("http://freegeoip.net/json");

Invocation.Builder invoc = wt.request();

Response ergebnis = invoc.get();

System.out.println(ergebnis);

ergebnis.bufferEntity(); // sonst Fehler bei 42

System.out.println(ergebnis.getEntity());

for(String s:ergebnis.getHeaders().keySet()){

System.out.println(s +": " + ergebnis.getHeaders().get(s));

}

System.out.println(ergebnis.readEntity(JsonObject.class));

System.out.println(ergebnis.getEntity().getClass()); //42

ergebnis.close();

}Komponentenbasierte Software-

Entwicklung

Page 97: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

665

Externer Service zur Analyse von IPs (4/4)

ScopedJaxrsResponse{ClientResponse{method=GET,

uri=http://freegeoip.net/json, status=200, reason=OK}}

java.io.ByteArrayInputStream@6d420a24

Date: [Wed, 14 May 2014 17:48:10 GMT]

Access-Control-Allow-Origin: [*]

Content-Length: [222]

Content-Type: [application/json]

{"ip":"93.196.192.46","country_code":"DE","country_name":"Germany","

region_code":"07","region_name":"Nordrhein-

Westfalen","city":"Hopsten","zipcode":"","latitude":52.3833,"longitu

de":7.6167,"metro_code":"","area_code":""}

class java.io.ByteArrayInputStream

Komponentenbasierte Software-Entwicklung

Page 98: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

666

Übergabe von Aufrufparametern (1/2)

@GET

@Produces(MediaType.APPLICATION_JSON)

@Path("/rechnen")

public JsonObject machMathe(

@QueryParam("op1") int op1,

@QueryParam("op2") int op2,

@DefaultValue("plus")

@QueryParam("operator") String operator) {

JsonObjectBuilder erg = Json.createObjectBuilder();

if(operator.equals("minus")){

return erg.add("operator", operator)

.add("ergebnis", (op1-op2)).build();

}

return erg.add("operator", "plus")

.add("ergebnis", (op1+op2)).build();

}

Komponentenbasierte Software-Entwicklung

Page 99: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

667

Übergabe von Aufrufparametern (2/2)

Komponentenbasierte Software-Entwicklung

Page 100: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

668

Dienstnutzung mit Aufrufparametern (1/2)

public static void main(String[] s) {

String SERVICE

= "http://maps.googleapis.com/maps/api/geocode/json";

Client client = ClientBuilder.newClient();

WebTarget wt = client.target(SERVICE +

"?address=Quakenbrueck&sensor=false");

Invocation.Builder invoc = wt.request();

JsonObject ergebnis = invoc.get(JsonObject.class);

System.out.println(ergebnis);

JsonObject details = ((JsonArray)ergebnis.get("results"))

.getJsonObject(0);

JsonObject position= (JsonObject)

((JsonObject)details.get("geometry")).get("location");

System.out.println(position);

}

Komponentenbasierte Software-Entwicklung

Page 101: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

669

Dienstnutzung mit Aufrufparametern (2/2)

{"results":[{"address_components":[{"long_name":"Quakenbrück","

short_name":"Quakenbrück","types":["locality","political"]},{"l

ong_name":"Osnabrück","short_name":"OS","types":["administrativ

e_area_level_3","political"]},{"long_name":"Lower

Saxony","short_name":"NDS","types":["administrative_area_level_

1","political"]},{"long_name":"Germany","short_name":"DE","type

s":["country","political"]}],"formatted_address":"Quakenbrück,

Germany","geometry":{"bounds":{"northeast":{"lat":52.6967289,"l

ng":8.0344312},"southwest":{"lat":52.65917049999999,"lng":7.903

767999999999}},"location":{"lat":52.675599,"lng":7.950777699999

999},"location_type":"APPROXIMATE","viewport":{"northeast":{"la

t":52.6967289,"lng":8.0344312},"southwest":{"lat":52.6591704999

9999,"lng":7.903767999999999}}},"types":["locality","political"

]}],"status":"OK"}

{"lat":52.675599,"lng":7.950777699999999}

Komponentenbasierte Software-Entwicklung

Page 102: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

670

Aufgabe

Sprinter soll um eine RESTful-Schnittstelle ergänzt werden,

• mit der von außen auf Sprints zugegriffen werden kann,

• die nur eine Teilmenge der Daten der Sprints sieht,

• die neue Sprints anlegen kann,

• die Sprints editieren kann,

• die Sprints löschen kann

• Entscheidung: Ergänze Programm um RESTful Webservices

• Schnittstelle wird in neuem Projekt genutzt (das zum einfacheren Verständnis eine JSF-Oberfläche bekommt)

Komponentenbasierte Software-Entwicklung

Page 103: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

671

Nutzungsszenario

• Links nicht ausimplementiert

Komponentenbasierte Software-Entwicklung

Page 104: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

672

Architektur: hierarchischer Aufbau

Resource POST(CREATE)

GET(READ)

PUT(UPDATE)

DELETE(DELETE)

/sprints erzeugt neuen Sprint

Übersicht über alle Sprints

Aktualisiere alle Sprints (oder weglassen)

alle Sprints löschen

/sprints/42 Fehler! Zeige Sprint mit id 42

wenn Sprint mit id 42 existiert, dann aktualisieren, (sonst Fehler ?)

Lösche den Sprint mit id42

Hinweise: noch sauberer wäre /sprint/42 (Einzahl)graue Felder nicht realisiert

Komponentenbasierte Software-Entwicklung

Page 105: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

673

Einordnung SprintRestController (Server)

Komponentenbasierte Software-Entwicklung

Page 106: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

674

Client (minimal)

Komponentenbasierte Software-Entwicklung SprinterRESTClient

Page 107: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

675

Vorbereitung im Server

@Stateless // oder @Singleton

@Path("")

public class SprintRestController implements Serializable{

@Inject

private PersistenzService pers;

@Context

private UriInfo uriInfo; // später genauer

private SimpleDateFormat formatter

= new SimpleDateFormat("dd.MM.yyyy");

public SprintRestController() {

}

Komponentenbasierte Software-Entwicklung

Page 108: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

676

Hilfsmethode zum Sprint einpacken

private JsonObject jsonSprint(Sprint s, boolean einzeln) {

String idzeigen = (einzeln) ? "" : "" + s.getId();

JsonObjectBuilder js = Json.createObjectBuilder();

js.add("id", s.getId())

.add("motto", s.getMotto())

.add("starttermin", formatter.format(s.getStarttermin()))

.add("endtermin", formatter.format(s.getEndtermin()))

.add("geplanterAufwand", s.getGeplanterAufwand())

.add("farbe", s.color())

.add("link", uriInfo.getAbsolutePathBuilder()

.path(idzeigen + "/backlogElemente")

.build().getPath());

return js.build();

}

Komponentenbasierte Software-Entwicklung

Page 109: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

677

GET /sprints (1/2)

@GET

@Produces({MediaType.APPLICATION_JSON})

@Path("/sprints")

public JsonObject getSprints(

@DefaultValue("-1") @QueryParam("von") int von,

@DefaultValue("-1") @QueryParam("bis") int bis) {

List<Sprint> alle = pers.findAllSprint();

if (von < 0 || von >= alle.size()) {

von = 0;

}

if (bis < 0 || bis >= alle.size()) {

bis = alle.size() - 1;

}

Komponentenbasierte Software-Entwicklung

Page 110: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

678

GET /sprints (2/2)

JsonArrayBuilder elemente = Json.createArrayBuilder();

for (int i = von; i <= bis; i++) {

elemente.add(jsonSprint(alle.get(i), false));

}

return Json.createObjectBuilder()

.add("sprints", elemente)

.build();

}

Komponentenbasierte Software-Entwicklung

Page 111: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

679

Client – Vorbereitung (1/2)

• Client braucht keine echte Datenhaltung

• Ansatz: Daten lokal in SessionScope halten (für kleinere Datenmengen ok

@Named

@SessionScoped

public class SprintController implements Serializable {

private Client client;

private List<Map<String, Object>> sprints;

private final static String[] keys = {"id", "motto"

, "starttermin", "endtermin", "geplanterAufwand"

, "link", "farbe"};

private final static String SPRINTS

= "http://localhost:8080/Sprinter/resources/sprints";

private final static String HOME = "index";

Komponentenbasierte Software-Entwicklung

Page 112: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

680

Client – Vorbereitung (2/2)

• eine Variable pro Eigenschaft mit get und setenum Status {BASIC, EDIT;}

private long id;

private String motto;

private Date starttermin;

private Date endtermin;

private int geplanterAufwand;

private Status modus;

private String meldung = ""; // Statusmeldung ohne Voodoo

SimpleDateFormat formatter

= new SimpleDateFormat("dd.MM.yyyy");

public SprintController() {

}

Komponentenbasierte Software-Entwicklung

Page 113: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

681

Client – Initialisierung (1/2)

@PostConstruct

public void init() {

this.modus = Status.BASIC;

this.client = ClientBuilder.newClient();

WebTarget wt = client.target(SPRINTS);

Invocation.Builder buil = wt

.request(MediaType.APPLICATION_JSON);

JsonObject ergebnis = buil.get(JsonObject.class);

JsonArray array = ergebnis.getJsonArray("sprints");

this.sprints = new ArrayList<Map<String, Object>>();

for (JsonValue val : array) {

JsonObject js = (JsonObject) val;

// speichert einen String als Attribut/Wert-Paar

Map<String, Object> werte = new HashMap<String, Object>();

Komponentenbasierte Software-Entwicklung

Page 114: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

682

Client – Initialisierung (2/2)

for (String k : keys) {

werte.put(k, js.get(k));

}

this.sprints.add(werte);

}

this.motto = "";

this.starttermin = null;

this.endtermin = null;

this.geplanterAufwand = 0;

} in älteren Versionen überflüssige " entfernen for (String k : keys) {

Object tmp = js.get(k);

String txt = tmp.toString();

if(txt.startsWith("\"") && txt.endsWith("\"") && txt.length() > 1){

tmp = txt.substring(1, txt.length()-1);

}

werte.put(k, tmp);

Komponentenbasierte Software-Entwicklung

Page 115: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

683

Erfolgloses Löschen möglich

• vom anderen Nutzer gelöscht oder modifiziert

• Idempotent wäre, diesen Fehler zu ignorieren (ist gelöscht)

Komponentenbasierte Software-Entwicklung

Page 116: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

684

Server Action loeschen

@DELETE

@Path("/sprints/{id}")

public JsonObject loeschen(@PathParam("id") long id) {

pers.removeSprint(id);

JsonObjectBuilder js = Json.createObjectBuilder();

js.add("status", "geloescht");

return js.build();

}

Komponentenbasierte Software-Entwicklung

Page 117: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

685

Client löschen

public String loeschen(Object sid) {

System.out.println("loeschen: " + sid);

WebTarget wb = client.target(SPRINTS + "/" + sid);

Invocation.Builder build = wb

.request(MediaType.APPLICATION_JSON);

try {

JsonObject ergebnis = build.delete(JsonObject.class);

this.meldung = "loeschen erfolgreich: " + ergebnis;

} catch (Exception e) {

this.meldung = "loeschen gescheitert: " + e;

}

init();

this.modus = Status.BASIC;

return HOME;

}Komponentenbasierte Software-

Entwicklung

Page 118: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

686

Neuer Sprint – Server (1/2)

@POST

@Produces(MediaType.APPLICATION_JSON)

@Consumes(MediaType.APPLICATION_JSON)

@Path("/sprints")

public JsonObject hinzufuegen(JsonObject jo) {

Sprint sprint = new Sprint();

sprint.setMotto(jo.getString("motto"));

sprint.setGeplanterAufwand(jo.getInt("geplanterAufwand"));

SimpleDateFormat formatter

= new SimpleDateFormat("dd.MM.yyyy");

try {

sprint.setStarttermin(formatter

.parse(jo.getString("starttermin")));

Komponentenbasierte Software-Entwicklung

Page 119: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

687

Neuer Sprint – Server (2/2)

sprint.setEndtermin(formatter

.parse(jo.getString("endtermin")));

} catch (ParseException ex) {

return null;

}

pers.persist(sprint);

JsonObjectBuilder js = Json.createObjectBuilder();

js.add("link"

, uriInfo.getAbsolutePathBuilder()

.path(sprint.getId() + "/backlogElemente")

.build().getPath());

return js.build();

}

Komponentenbasierte Software-Entwicklung

Page 120: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

688

Neuer Sprint – Client Aktion uebernehmen (1/4)

public String uebernehmen() {

// Validerung des Clients muss dieser regeln

if (this.starttermin == null || this.endtermin == null){

this.meldung = "Start- und Endtermin angeben!";

return HOME;

}

if (this.starttermin.compareTo(this.endtermin) > 0){

this.meldung = "Endtermin nicht vor Starttermin";

return HOME;

}

Komponentenbasierte Software-Entwicklung

Page 121: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

689

Neuer Sprint – Client Aktion uebernehmen (2/4)

JsonObjectBuilder js = Json.createObjectBuilder();

js.add("motto", this.motto)

.add("starttermin", formatter.format(this.starttermin))

.add("endtermin", formatter.format(this.endtermin))

.add("geplanterAufwand", this.geplanterAufwand);

if (this.modus.equals(Status.BASIC)) {

neuerSprint(js);

}

if (this.modus.equals(Status.EDIT)) {

editiereSprint(js);

}

init();

this.modus = Status.BASIC;

return HOME;

}Komponentenbasierte Software-

Entwicklung

Page 122: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

690

Neuer Sprint – Client Aktion uebernehmen (3/4)

private void neuerSprint(JsonObjectBuilder js){

WebTarget wb = client.target(SPRINTS);

Invocation.Builder build = wb

.request(MediaType.APPLICATION_JSON);

Entity entity = Entity.entity(js.build()

, MediaType.APPLICATION_JSON);

try {

JsonObject ergebnis = build.post(entity, JsonObject.class);

this.meldung = "einfuegen erfolgreich: " + ergebnis;

} catch (Exception e) {

this.meldung = "einfuegen gescheitert: " + e;

}

}

Komponentenbasierte Software-Entwicklung

Page 123: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

691

Sprint editieren – Server (1/2)

@PUT

@Produces(MediaType.APPLICATION_JSON)

@Consumes(MediaType.APPLICATION_JSON)

@Path("/sprints/{id}")

public JsonObject aktualisieren( @PathParam("id") long id

, JsonObject jo) {

Sprint sprint = pers.findSprint(id);

sprint.setMotto(jo.getString("motto"));

sprint.setGeplanterAufwand(jo.getInt("geplanterAufwand"));

try {

sprint.setStarttermin(formatter

.parse(jo.getString("starttermin")));

sprint.setEndtermin(formatter

.parse(jo.getString("endtermin")));

Komponentenbasierte Software-Entwicklung

Page 124: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

692

Sprint editieren – Server (2/2)

} catch (ParseException ex) {

return null;

}

pers.merge(sprint);

JsonObjectBuilder js = Json.createObjectBuilder();

js.add("link"

, uriInfo.getAbsolutePathBuilder()

.path("/backlogElemente").build().getPath());

return js.build();

}

Komponentenbasierte Software-Entwicklung

Page 125: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

693

Editiere Sprint – Client Aktion uebernehmen (4/4)

private void editiereSprint(JsonObjectBuilder js) {

WebTarget wb = client.target(SPRINTS + "/" + this.id);

Invocation.Builder build = wb

.request(MediaType.APPLICATION_JSON);

js.add("id", id);

Entity entity = Entity.entity(js.build()

, MediaType.APPLICATION_JSON);

try {

JsonObject ergebnis = build.put(entity, JsonObject.class);

this.meldung = "aktualisieren erfolgreich: " + ergebnis;

} catch (Exception e) {

this.meldung = "aktualisieren gescheitert: " + e;

}

}

Komponentenbasierte Software-Entwicklung

Page 126: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

694

UriInfo (1/2)

@Path("ana")

@Stateless

public class Analyse {

@Context

private UriInfo uriInfo;

private final static Logger LOGGER = Logger

.getLogger(Analyse.class.getSimpleName());

@GET

@Produces(MediaType.TEXT_PLAIN)

public String getText() {

LOGGER.info("in getText");

LOGGER.info(this.uriInfo.getAbsolutePath().toString());

Komponentenbasierte Software-Entwicklung

Page 127: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

695

UriInfo (2/2)

LOGGER.info(this.uriInfo.getPath());

LOGGER.info(this.uriInfo.getRequestUri().toString());

for (String s:this.uriInfo.getQueryParameters().keySet()){

LOGGER.info(s+ ": "

+ this.uriInfo.getQueryParameters().get(s));

}

return "hai";

}

INFO: in getText

INFO: http://localhost:8080/resources/ana

INFO: /ana

INFO: http://localhost:8080/resources/ana?x=Hai&text=42

INFO: text: [42]

INFO: x: [Hai]

Komponentenbasierte Software-Entwicklung

Page 128: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

696

WADL (1/3)

• Web Application Description Language

• XML-basierte Beschreibung angebotener Dienste

• generell soll HTTP-Befehl OPTIONS genutzt werden, um Übersicht zu erhalten

• Alle möglichen Dienste mit Parametern werden aufgeführt

• Dienstbeschreibungen können aus Annotation generiert werden

• Alternativ kann @OPTIONS-annotierte Methode realisiert werden (z. B. um Ausgabe zu verhindern)

• Bedeutung eher gering, für Werkzeuge basierend auf WADL-Services interessant; erkennen so Aktualisierungen

Komponentenbasierte Software-Entwicklung

Page 129: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

697

WADL (2/3) - Beispielmethode

@GET

@Produces("text/html")

public String getHtml() {

return "<html><body>Hello, World!!</body></html>";

}

<resources base="http://localhost:8080/resources/">

<resource path="helloworld">

<method id="getHtml" name="GET">

<response>

<representation mediaType="text/html"/>

</response>

</method>

...

Komponentenbasierte Software-Entwicklung

Page 130: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

698

WADL (3/3) – Beispiel aus Sprinter

<resources base="http://localhost:8080/Sprinter/resources/">

<resource path="sprints">

<method id="getSprints" name="GET">

<request>

<param xmlns:xs="http://www.w3.org/2001/XMLSchema"

name="von"

style="query" type="xs:int" default="-1"/>

<param xmlns:xs="http://www.w3.org/2001/XMLSchema"

name="bis"

style="query" type="xs:int" default="-1"/>

</request>

<response>

<representation mediaType="application/json"/>

</response>

</method>

<method id="hinzufuegen" name="POST">

<request>

<representation mediaType="application/json"/>

</request>

<response>

<representation mediaType="application/json"/>

</response>

Komponentenbasierte Software-Entwicklung

Page 131: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

699

@FormParam

<form action="http://vfl.de/mitglieder" method="post">

<p>

Vorname: <input type="text" name="vorname"><br>

Nachname: <input type="text" name="nachname"><br>

<input type="submit" value="Send">

</p>

</form>

@Path("/mitglieder")

@Consumes(Mediatype.APPLICATION_FORM_URLENCODED)

public class CustomerResource {

@POST

public void createCustomer(

@FormParam(“vorname") String vorname

, @FormParam(“nachname") String nachname) {

...

}

ermöglicht die Übernahme von Parametern einer POST-Anfrage eines HTML-Formulars

Komponentenbasierte Software-Entwicklung

Page 132: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

700

Response.Status (gibt evtl. passende Exceptions)public enum Status {

OK(200, "OK"), CREATED(201, "Created"),

ACCEPTED(202, "Accepted"),

NO_CONTENT(204, "No Content"),

MOVED_PERMANENTLY(301, "Moved Permanently"),

SEE_OTHER(303, "See Other"),

NOT_MODIFIED(304, "Not Modified"),

TEMPORARY_REDIRECT(307, "Temporary Redirect"),

BAD_REQUEST(400, "Bad Request"),

UNAUTHORIZED(401, "Unauthorized"),

FORBIDDEN(403, "Forbidden"),

NOT_FOUND(404, "Not Found"),

NOT_ACCEPTABLE(406, "Not Acceptable"),

CONFLICT(409, "Conflict"), GONE(410, "Gone"),

PRECONDITION_FAILED(412, "Precondition Failed"),

UNSUPPORTED_MEDIA_TYPE(415, "Unsupported Media Type"),

INTERNAL_SERVER_ERROR(500, "Internal Server Error"),

SERVICE_UNAVAILABLE(503, "Service Unavailable");

Komponentenbasierte Software-Entwicklung

Page 133: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

701

Weiterführend (1/2)

• asynchron@POST

@Asynchronous public void bearbeite(

@Suspended AsyncResponse ar, Daten daten)

• reguläre Ausdrücke in Path, @Path("{id : .+}")

komplexe Auswertungsregeln, was, wenn mehrere Möglichkeiten an Pfaden existieren

• HEAD: nimmt typischerweise erste GET und gibt statt Ergebnis nur Header und Response-Code zurück

• MIME-Types können sehr detailliert sein, generelltype/subtype;name=value;name=value...

@Consumes("application/xml;charset=utf-8")

Komponentenbasierte Software-Entwicklung

Page 134: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

702

Weiterführend (2/2)

• JAX-RS-Annotationen können auch nur in Interfaces ausgelagert werden

• Matrix-Parameter (Attribute) behandelbarhttp://beispiel.spieler.de/vfl;typ=Sturm/2015

• Nutzung von Header-Parametern @HeaderParampublic String get(@HeaderParam("Referrer") String

aufrufer) {

public String get(@Context HttpHeaders headers) {

• Cookie-Nutzung public String get(@CookieParam(“minr") int minr)

• genauere Analyse vom ResponseBuilder.status(.)

• Einbindung von Bean Validation

• …

Komponentenbasierte Software-Entwicklung

Page 135: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

703

Literatur

• (Standard-Links sind im Text)

• [Bur14] B. Burke, RESTful Java with JAX-RS 2.0, O‘Reilly, Sebastopol (CA), USA, 2014

• http://www.oracle.com/technetwork/articles/java/jaxrs20-1929352.html

Komponentenbasierte Software-Entwicklung

Page 136: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

704

8. WebSockets

• WebSockets

– Verbreitung

– zentrale Nachrichten

– Realisierung eines Chats

– Encoder

– Decoder

• Bedeutung von JavaScript

basiert teilweise auf: [Dit14] A. Ditler, Prototypische Realisierung eines Echtzeit-Webchats als Crossplattform-Applikation auf Basis von Websockets, Hochschule Osnabrück, Bachelorarbeit, 2014

Komponentenbasierte Software-Entwicklung

Page 137: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

705

WebSockets - Motivation

• HTTP erlaubt nur die Beantwortung von Client-Anfragen

• ohne Erweiterung keine Möglichkeit, dass der Server den Client nachträglich ohne erneute Anfrage informiert

• nur mit Workaround z. B. AJAX und Long-Polling möglich

• WebSockets erlauben die bidirektionale Kommunikation zwischen Client und Server

• allgemein: The WebSocket API, W3C Candidate Recommendation, 20.09.2012, http://www.w3.org/TR/websockets/

• standardisiert in Java: JSR 356: JavaTM API for WebSocket, https://jcp.org/en/jsr/detail?id=356

Komponentenbasierte Software-Entwicklung

Page 138: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

706

Verbreitung (1/2)

• aktuell wird Ansatz in vielen Projekten evaluiert, Nutzung hängt von Zielplattformen ab

• Anmerkung: Abkündigung von Win XP-Support lässt alte IE-Browser verschwinden

• genauer müssen unterstütze Prokollversionen (ab wann) und Zielplattformen zusammen evaluiert werden

• Beispiel: Android-Browser erst ab Android 4.4, andere Browser für Android schon eher

• Beispiel: Web-Seite soll auch zur App auf Handys werden, ein Ansatz mit Apache Cordova / Phonegap, unterstützt nur etwas ältere WebSocket-Version

Komponentenbasierte Software-Entwicklung

Page 139: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

707

Verbreitung (2/2)

aktueller Stand: http://caniuse.com/websockets

• IE ab 10.0, Edge ab Start

• Firefox ab 11.0

• Chrome ab 16

• Safari ab 7.0

• Opera ab 12.1

• iOS Safari ab 6.1

• Android Browser ab 4.4

• Blackberry Browser ab 7.0

• Chrome for Android ab 33.0

• Firefox for Android ab 26

• IE Mobile ab 10.0

Komponentenbasierte Software-Entwicklung

Page 140: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

708

grobe Funktionsweise / Potenzial

• Client und Server in Java möglich, genauso gut können aber Clients in anderen Sprachen geschrieben werden (Server auch)

• Verbindung mit Server wird über HTTP hergestellt, Server dabei auf Upgrade auf WebSocket-Protokoll befragt

typische Adresse: new URI("ws://localhost:1790/hallo/echo")

• wenn Server Upgrade anbietet, wird bidirektional nutzbare Verbindung aufgebaut (ohne dass diese physikalisch gehalten werden muss)

• wenn Server kein Upgrade anbietet, ist Ansatz gescheitert

• es gibt verschiedene Protokoll-Versionen, auch hier muss sich auf eine geeinigt werden

Komponentenbasierte Software-Entwicklung

Page 141: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

709

etwas Hintergrund

• Auf TCP basierendes Netzwerkprotokoll

• Bidirektionale – Vollduplex Kommunikation

• Verbindung basiert auf einem einzigen Socket

• Datenübertragung mit geringer Latenzzeit

• Datenaustausch: binär, utf-8, …, nur Zeichenketten oder Byte-Buffer

• Websocket-Verbindung: ws:// und wss://

• keine Probleme bei Firewalls und Proxy-Servern

• Referenzimplementierung: Tyrus https://tyrus.java.net/

• Alternativen: GNU WebSocket4J, Webbit, Tootallnate

Komponentenbasierte Software-Entwicklung

Page 142: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

710

zentrale Nachrichten

Server Client

onOpen Verbindungsaufbau onOpen

onMessage senden und empfangen onMessage

onClose Verbindungsabbau onClose

onError Fehlerfall onError

eigentliches Protokoll, was in welcher Form ausgetauscht wird, muss von Entwicklern festgelegt werden

Begriff „Socket“ kann ernst genommen werden

Komponentenbasierte Software-Entwicklung

Page 143: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

711

Erstes Beispiel (1/7): Gewünscht

Client Server

connectToServer

@OnOpen (Bestätigung)

send(Hello) @OnMessage

@OnMessage send(Hallo Client)

send(Hello again) @OnMessage

@OnMessage send(Hallo Client)

(schließen) @OnClose

@OnClose (Bestätigung)

Komponentenbasierte Software-Entwicklung

Page 144: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

712

Erstes Beispiel (2/7): Server (1/2)

@ServerEndpoint("/echo")

public class EchoServer {

@OnOpen

public void onOpen(Session session, EndpointConfig cfg) {

System.out.println("@Server Anfrage URI: "

+ session.getRequestURI());

}

@OnMessage

public void onMessage(String message, Session session)

throws IOException {

System.out.println("@Server Nachricht: " + message);

session.getBasicRemote().sendText("Hallo Client");

}

Komponentenbasierte Software-Entwicklung

Page 145: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

713

Erstes Beispiel (3/7): Server (2/2)

@OnClose

public void onClose(Session session

, CloseReason closeReason) {

System.out.println("@Server CloseReason: "

+ closeReason);

}

@OnError

public void onError(Session session, Throwable thr) {

System.out.println("@Server Error: " + thr);

}

}

Komponentenbasierte Software-Entwicklung

Page 146: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

714

Erstes Beispiel (4/7): Client (1/3)

@ClientEndpoint

public class EchoClient {

@OnOpen

public void onOpen(Session session, EndpointConfig config) {

System.out.println("Id: " + session.getId()

+ "\nnegotiated: " + session.getNegotiatedSubprotocol()

+ "\nProtocol Version: " + session.getProtocolVersion()

+ "\nQuery String: " + session.getQueryString()

+ "\nRequestURI: " + session.getRequestURI()

+ "\nMaxIdleTimeout:" + session.getMaxIdleTimeout());

}

Komponentenbasierte Software-Entwicklung

Page 147: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

715

Erstes Beispiel (5/7): Client (2/3)

@OnMessage

public void onMessage(String message, Session session)

throws IOException {

System.out.println("@Client empfangen: " + message);

}

@OnClose

public void onClose(Session session, CloseReason closeReason) {

System.out.println("@Client CloseCode: "

+ closeReason.getCloseCode() + "\n@Client ReasonPhrase:"

+ closeReason.getReasonPhrase());

}

@OnError

public void onError(Session session, Throwable thr) {

System.out.println("@Client Error: " + thr);

}Komponentenbasierte Software-

Entwicklung

Page 148: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

716

Erstes Beispiel (6/7): Client (3/3)

public static void main(String[] args) {

WebSocketContainer container = ContainerProvider

.getWebSocketContainer();

try (Session session = container

.connectToServer(EchoClient.class, URI.create(

"ws://localhost:8080/WebSocketHelloWorld/echo"))) {

session.getBasicRemote().sendText("Hello");

session.getBasicRemote().sendText("Hello again");

System.out.println("1: " + session.isOpen());

session.close(new CloseReason( CloseCodes.NORMAL_CLOSURE

, "Schicht"));

System.out.println("2: " + session.isOpen());

} catch (Exception e) {

e.printStackTrace();

}

}

Komponentenbasierte Software-Entwicklung

Page 149: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

717

Erstes Beispiel (7/7): Ausgabe

Id: 2d80aea7-3d60-4a59-aaeb-56844cbbc25e

negotiated:

Protocol Version: 13

Query String: null

RequestURI: ws://localhost:8080/vlWebSocketEcho/echo

MaxIdleTimeout:0

1: true

@Client CloseCode: NORMAL_CLOSURE

@Client ReasonPhrase:Schicht

2: false

@Client empfangen: Hallo Client

INFO: @Server Anfrage URI: /vlWebSocketEcho/echo

INFO: @Server Nachricht: Hello

INFO: @Server Nachricht: Hello again

INFO: @Server CloseReason: CloseReason[1000,Schicht]

Komponentenbasierte Software-Entwicklung

Page 150: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

718

Analyse des ersten Beispiels

• Client und Server unterscheiden sich im Wesentlichen nur durch Annotationen @ClientEndpoint und @ServerEndpoint

• in JEE-Container führt @ServerEndpoint automatisch zum Deployen (läuft)

• beide nutzen @OnOpen, @OnMessage, @OnClose und gegebenenfalls @OnError

• zeigt Symmetrie der Kommunikationspartner

• wichtige (zu verwaltende) Objekte vom Typ Session

• Beispiel zeigt, dass es vom Timing abhängt, ob Bestätigung der zweiten Nachricht noch ankommt!

• keine explizite Nutzung von Threads notwendig; da paralleler Zugriff aber Synchronisation eventuell wichtig

Komponentenbasierte Software-Entwicklung

Page 151: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

719

2. Fallstudie (1/7): Realisierung eines Chats

• Clients können sich beim Server zum Chatten anmelden

• jede geschickte Nachricht wird an alle anderen verteilt

• Abmelden mit Nachricht „bye“ möglich

• (da wieder nur textbasiert, Überlappungen in Ein- und Ausgabe möglich)

• Server verwaltet Client-Sessions in einer synchronisierten Collection

Komponentenbasierte Software-Entwicklung

Page 152: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

720

2. Fallstudie (2/7): Server 1/2

@ServerEndpoint("/chat")

public class ChatServer {

private static Set<Session> partner =

Collections.synchronizedSet(new HashSet<Session>());

@OnOpen

public void onOpen(Session session, EndpointConfig config) {

this.partner.add(session);

}

@OnMessage

public void onMessage(String msg, Session s) throws IOException {

sende(msg);

}

@OnClose

public void onClose(Session session, CloseReason closeReason) {

this.partner.remove(session);

}

Komponentenbasierte Software-Entwicklung

Page 153: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

721

2. Fallstudie (3/7): Server 2/2

private void sende(String nachricht) {

try {

// nebenbei aufraeumen

List<Session> geschlossen = new ArrayList<>();

for (Session s : this.partner) {

if (!s.isOpen()) {

System.err.println("Geschlossen: " + s.getId());

geschlossen.add(s);

} else {

s.getBasicRemote().sendText(nachricht);

}

}

this.partner.removeAll(geschlossen);

System.out.println("Sende " + nachricht + " an "

+ this.partner.size() + " Klienten");

} catch (Throwable e) {

e.printStackTrace();

}

}

Komponentenbasierte Software-Entwicklung

Page 154: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

722

2. Fallstudie (4/7): Client 1/2

@ClientEndpoint

public class ChatClient {

@OnOpen

public void onOpen(Session session, EndpointConfig cfg) {

System.out.println("verbunden");

}

@OnMessage

public void onMessage(String msg, Session s) throws IOException {

System.out.println("@Client empfangen: " + msg);

}

@OnClose

public void onClose(Session session, CloseReason closeReason) {

System.out.println("abgemeldet");

}

Komponentenbasierte Software-Entwicklung

Page 155: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

723

2. Fallstudie (5/7): Client 2/2

public static void main(String[] args) {

WebSocketContainer container = ContainerProvider

.getWebSocketContainer();

try (Session session = container.connectToServer(ChatClient.class

, URI.create("ws://localhost:8080/WebSocketChat/chat"))) {

String eingabe= "";

while (!eingabe.toLowerCase().equals("bye")){

System.out.print("Beitrag: ");

eingabe = new Scanner(System.in).nextLine();

session.getBasicRemote().sendText(eingabe);

}

session.close(new CloseReason(CloseReason.CloseCodes

.NORMAL_CLOSURE, "Schicht"));

} catch (Exception e) {

e.printStackTrace();

}

}

} Komponentenbasierte Software-Entwicklung

Page 156: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

724

2. Fallstudie (6/7): Ausgabe (Eingaben markiert)

Beitrag: verbunden

Wer ist da

Beitrag: @Client

empfangen: Wer ist da

@Client empfangen:

ich

@Client empfangen:

ich auch

@Client empfangen:

bye

@Client empfangen:

bye

bye

@Client empfangen:

bye

abgemeldet

Beitrag: verbunden

@Client empfangen:

Wer ist da

ich

Beitrag: @Client

empfangen: ich

@Client empfangen:

ich auch

@Client empfangen:

bye

bye

@Client empfangen:

bye

abgemeldet

Beitrag: verbunden

@Client empfangen:

Wer ist da

@Client empfangen:

ich

ich auch

Beitrag: @Client

empfangen: ich auch

bye

@Client empfangen:

bye

abgemeldet

Komponentenbasierte Software-Entwicklung

Page 157: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

725

2. Fallstudie (7/7): Ausgabe Server

INFO: Sende Wer ist da an 3 Klienten

INFO: Sende ich an 3 Klienten

INFO: Sende ich auch an 3 Klienten

INFO: Sende bye an 3 Klienten

INFO: Sende bye an 2 Klienten

INFO: Sende bye an 1 Klienten

Komponentenbasierte Software-Entwicklung

Page 158: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

726

Ein- und Auspacken

• Zum Verschicken von Objekten werden sie in einfache Strings verwandelt

• hier bietet sich wieder JSON an

• für benötigte Klassen werden Encoder und Decoder geschrieben, die dem Client und Server bekannt gemacht werden

• folgendes Beispiel: Austausch von Sprint-Informationen mit JavaScript-Client (sehr elementar gehalten)

• Auch ByteStreams übertragbar

Komponentenbasierte Software-Entwicklung

Page 159: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

727

Sprint- Fallstudie (1/14): Sprints encoden 1/2

public class SprintsEncoder

implements Encoder.TextStream<List<Sprint>> {

@Override

public void encode(List<Sprint> sprints, Writer writer) {

JsonProvider provider = JsonProvider.provider();

JsonArrayBuilder elemente = Json.createArrayBuilder();

for (Sprint s : sprints) {

elemente.add(jsonSprint(s, false)); // von REST bekannt

}

JsonObject js = Json.createObjectBuilder()

.add("sprints", elemente).build();

try (JsonWriter jsonWriter =

provider.createWriter(writer)) {

jsonWriter.write(js);

}

}

was soll codiert werden

Komponentenbasierte Software-Entwicklung

Page 160: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

728

Sprint- Fallstudie (2/14): Sprints encoden 2/2

@Override

public void init(EndpointConfig config) {

}

@Override

public void destroy() {

}

//leider Copy & Paste

private JsonObject jsonSprint(Sprint s, boolean einzeln) {

...

}

Komponentenbasierte Software-Entwicklung

Page 161: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

729

Sprint- Fallstudie (3/14): Sprint decoden 1/2

public class SprintDecoder

implements Decoder.TextStream<Sprint> {

private SimpleDateFormat formatter

= new SimpleDateFormat("dd.MM.yyyy");

@Override

public Sprint decode(Reader reader){

JsonProvider provider = JsonProvider.provider();

JsonReader jsonReader = provider.createReader(reader);

JsonObject js = jsonReader.readObject();

Sprint sprint = new Sprint();

sprint.setMotto(js.getString("motto"));

try {

sprint.setStarttermin(formatter

.parse(js.getString("starttermin")));

was soll decodiert werden

Komponentenbasierte Software-Entwicklung

Page 162: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

730

Sprint- Fallstudie (4/14): Sprint decoden 2/2

sprint.setEndtermin(formatter

.parse(js.getString("endtermin")));

} catch (ParseException ex) {}

try {

sprint.setGeplanterAufwand(js.getInt("geplanterAufwand"));

} catch (Exception e){

sprint.setGeplanterAufwand(Integer

.parseInt(js.getString("geplanterAufwand")));

}

return sprint;

}

@Override public void init(EndpointConfig config) {}

@Override public void destroy() {}

}Komponentenbasierte Software-

Entwicklung

Page 163: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

731

Sprint- Fallstudie (5/14): SprintServer 1/3

@ServerEndpoint(value="/socketsprint"

, encoders={SprintsEncoder.class}

, decoders={SprintDecoder.class})

public class SprintServer implements Serializable{

@Inject

PersistenzService pers;

private static Set<Session> partner = Collections

.synchronizedSet(new HashSet<Session>());

@OnOpen

public void onOpen(Session session, EndpointConfig cfg) {

this.partner.add(session);

sende(); // besser nur an einen

}

Komponentenbasierte Software-Entwicklung

Page 164: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

732

Sprint- Fallstudie (6/14): SprintServer 2/3

@OnMessage

public void onMessage(Sprint sprint, Session session)

throws IOException {

try{

this.pers.persist(sprint);

sende();

} catch (Exception e){

// Benachrichtigung an den Client fehlt

}

}

@OnClose

public void onClose(Session session, CloseReason cR) {

this.partner.remove(session);

}

hier wird Decodierung genutzt

Komponentenbasierte Software-Entwicklung

Page 165: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

733

Sprint- Fallstudie (7/14): SprintServer 3/3

public void sende() {

try {

List<Session> geschlossen = new ArrayList<>();

List<Sprint> sprints = pers.findAllSprint();

for (Session s : this.partner) {

if (!s.isOpen()) {

System.err.println("Geschlossen: " + s.getId());

geschlossen.add(s);

} else {

s.getAsyncRemote().sendObject(sprints);

}

}

this.partner.removeAll(geschlossen);

} catch (Throwable e) {

e.printStackTrace();

}

}

}

Komponentenbasierte Software-Entwicklung

Page 166: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

734

Sprint- Fallstudie (8/14): JavaScript-Client 1/6

<!DOCTYPE html>

<html>

<head>

<title>WebSocket Client für Sprints</title>

<meta http-equiv="Content-Type"

content="text/html; charset=UTF-8">

<script type="text/javascript" src="js/ws.js"></script>

</head>

<body>

<form name="felder">

<div id="eingabe">

Motto : <input type="text" id="motto"><br>

Starttermin: <input type="text" id="starttermin"><br>

Endtermin: <input type="text" id="endtermin"><br>

geplanter Aufwand: <input type="text"

id="geplanterAufwand"><br>

</div>

Komponentenbasierte Software-Entwicklung

Page 167: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

735

Sprint- Fallstudie (9/14): JavaScript-Client 2/6

<div id="button">

<input type="button" value="absenden"

onClick="sende();"><br>

<input type="button" value="beenden" onClick="ws.close();">

</div>

<div id="sprints"

style="background-color: white; margin:5px;">

</div>

</form>

</body>

</html>

Komponentenbasierte Software-Entwicklung

Page 168: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

736

Sprint- Fallstudie (10/14): JavaScript-Client 3/6

// Zuerst ueberpruefen, ob der Browser Websocket unterstuetzt

// wird am Ende des Scripts gestartet

if ("WebSocket" in window) {

var ws = new

WebSocket("ws://localhost:8080/Sprinter/socketsprint");

//wird bei erfolgreichem Verbindungsaufbau aufgerufen

ws.onopen = function() {

//alert("open");

};

// wird aufgerufen, wenn Server Daten schickt

ws.onmessage = function(event) {

// geht ohne eval

var objJSON = eval("(function()

{return " + event.data + ";})()");

document.getElementById("sprints")

.innerHTML = table(objJSON.sprints);

};Komponentenbasierte Software-

Entwicklung

Page 169: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

737

Sprint- Fallstudie (11/14): JavaScript-Client 4/6

//wird aufgerufen, wenn Verbindung geschlossen wurde

ws.onclose = function() {

alert("Client beendet Verbindung");

};

// Fehlermeldung

ws.onerror = function(error) {

alert("Ein Fehler ist aufgetretten " + error);

};

} else {

alert("Dein Browser ist zu alt");

}

Komponentenbasierte Software-Entwicklung

Page 170: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

738

Sprint- Fallstudie (12/14): JavaScript-Client 5/6

function sende() {

var sprint = {

motto: document.getElementById("motto").value,

starttermin: document.getElementById('starttermin').value,

endtermin: document.getElementById('endtermin').value,

geplanterAufwand:

document.getElementById('geplanterAufwand').value

};

//mit stringify zum JSON Objekt kodieren und abschicken

ws.send('' + JSON.stringify(sprint));

//Eingabefelder leeren

document.getElementById('motto').value = '';

document.getElementById('starttermin').value = '';

document.getElementById('endtermin').value = '';

document.getElementById('geplanterAufwand').value = '';

} Komponentenbasierte Software-Entwicklung

Page 171: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

739

Sprint- Fallstudie (13/14): JavaScript-Client 6/6

function table(data) {

var erg = "<table border='1'>";

erg += "<tr><th>Id</th><th>Motto</th><th>Start</th>";

erg += "<th>Ende</th><th>Geplanter Aufwand</th></tr>";

for (var i = 0; i < data.length; i++) {

erg += "<tr style='background-color:" + data[i].farbe + "'>";

erg += "<td>" + data[i].id + "</td>";

erg += "<td>" + data[i].motto + "</td>";

erg += "<td>" + data[i].starttermin + "</td>";

erg += "<td>" + data[i].endtermin + "</td>";

erg += "<td>" + data[i].geplanterAufwand + "</td>";

erg += "</tr>";

}

erg += "</table>";

return erg;

}Komponentenbasierte Software-

Entwicklung

Page 172: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

740

Sprint- Fallstudie (14/14): Beispielnutzung

Komponentenbasierte Software-Entwicklung

Page 173: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

741

nächste Schritte

• Anmerkung: Die Seite ist so mit Code-Injection angreifbar

• HTML-Client bekommt nicht mit, wenn in JSF-Applikation Sprint bearbeitet wird

• verschiedene Schritte denkbar

– Methode sende() von SprintServer wird aufgerufen, wenn ein Sprint-Objekt bearbeitet wird (z. B. in Persistieren einbauen)

– Persistierung erzeugt Events, wenn Sprint-Objekte bearbeitet werden, SprintServer abonniert diese

• nächste Folie; nur kleine Änderungen im SprintControllervon JSF (Änderungen durch REST-Client werden so nicht erkannt)

Komponentenbasierte Software-Entwicklung

Page 174: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

742

Verknüpfung JSF mit WebSocket-Server

@Named

@SessionScoped

public class SprintController implements Serializable {

@Inject

SprintServer server;

...

public String uebernehmen() { // analog loeschen

...

server.sende();

...

Komponentenbasierte Software-Entwicklung

Page 175: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

743

weitere Überlegung

Löschen und Bearbeiten prinzipiell kein Problem:

• es wird aber ein erweitertes Protokoll benötigt

• z. B. erste Eigenschaft gibt an, was gemacht werden soll

• dann würde nicht Sprint-Klasse sondern Befehlsklasse zum Dekodieren im Server genutzt

Weiterführend

• Übertragung von Byte-Streams, z. B, zum Verschicken von Bildern

Komponentenbasierte Software-Entwicklung

Page 176: 6. Contexts and Dependency Injection - home.edvsz.fh ...home.edvsz.fh-osnabrueck.de/skleuker/WS15_KbSE/WS15KbSE_Teil7.… · Prof. Dr. Stephan Kleuker 569 6. Contexts and Dependency

Prof. Dr. Stephan Kleuker

744

Bedeutung von JavaScript

• Ursprünglich war JavaScript nur Hilfssprache, um kleine Berechnungen und Modifikationen im Browser zu ermöglichen

• mit HTML 5 wurde JavaScript zur zentralen Sprache des Internets

• Software-Engineering mit JavaScript steckt noch in den Kinderschuhen

• keine Klassenbibliothek, keine Standard-Frameworks

• eine unübersichtliche Menge sehr kreativer Lösungen

• Beispiel Varianten vom MV*-Pattern

• viele gute Werkzeuge und Hilfsmittel: JQuery, Jasmine, Istanbul, Karma, Selenium, …

Komponentenbasierte Software-Entwicklung