Testtermin: 4.12.2020 Prüfungen:

1. 2020-09-22

2. 2020-09-25

  • Was ist ein REST-Service?

  • Präsentation 04_REST_Uebersicht besprochen (bis Folie 20 - EFSP)

  • 04_REST_Uebersicht

2.1. Begriff des Marshalling

marshalling
unmarshalling

3. 2020-09-29

maven Lifecycle

3.1. Mögliche REST-Clients

  • Browser

  • Browser-Extension

    • RESTClient

  • REST-Client in IDE (files mit .http-Endung)

  • CLI-clients

    • cURL

    • httpie http :8080/person Accept:application/json

  • Standalone Clients

    • Postman

    • Insomnia

  • Selbstprogrammierte Clients

3.2. MediaType in Produces

schränkt die möglichen MIME-Types ein

3.3. Rückgabetypen

  • String

  • Entity - Klasse

    • JAXB - XML-Binding (XML-Marshalling)

    • JSON-B - Json-Binding (Json-Marshalling)

  • JsonObject / JsonArray / JsonValue

  • Response

    • Statuscode kann gewählt werden

    • Header-Entries können hinzugefügt werden

    • uvam.

4. 2020-10-02

Was ist? (Erläuterung und Abrenzung)
  • Jakarta EE

  • microprofile

  • Quarkus

5. 2020-10-06

Mikroprojekte - Themenvergabe
lfd.Nr. Name Thema -

1

BM

Friedhofsverwaltung

2

DJ

Produktionsbetrieb (Fließband)

3

DF

Centermanager

4

EQ

Baustellenkoordinator

5

EP

Baumschule

6

FS

Kochrezepte

7

FJ

Farmverwaltung

8

HT

Optiker

9

KS

Facility Management

10

KF

Zooverwaltung

11

KS2

Event-Manager

12

MR

Reisebüro

13

MA

Plattenlabel

14

OJ

Tanzschule

15

PV

Skischule

16

RJ

Fitnessstudio

17

SS

Fakturierung

18

SL

Kfz-Händler

19

SM

Friseurladen

20

TS

Restaurant

21

TK

Callcenter

22

TI

Busreisen (inkl Schulbusse)

23

WN

Autovermietung

24

WJ

Parkplatzverwaltung

5.1. Assignment 01: Erstellen von Endpoints für eine Entität mit CRUD-Funktionalität

  • Erstellen Sie ein Quarkus-Projekt mit folgender Bezeichnung:

    1. nachname-projektname zB mustermann-restaurant

    2. Im Package at.htl.<projektname>.entity zB. at.htl.restaurant.entity erstellen Sie eine Entitätsklasse zB Product (in diesem Restaurant sind die Produkte die Speisen und Getränke)

    3. Die Daten der Stammdaten sind in einer Collection in einem geeigneten Repository zu speichern (Es ist KEINE Datenbank zu verwenden).

    4. Im Package at.htl.<projektname>.boundary (zB at.htl.restaurant.boundary) erstellen Sie ein Klasse <Entity>Service.java zB ProductService.java

    5. In dieser Klasse erstellen Sie mehrere Endpoints, um die CRUD-Funktionalität für die von Ihnen gewählte Entität zu implementieren.

    6. In einem File request.http erstellen Sie die geeigneten Request, um ihre Endppoints auzuprobieren

    7. Die Requests funktionieren mit Daten wahlweise im JSON- oder XML-Format

    8. Verwenden Sie Swagger, um Ihre Endpoints zu dokumentieren

    9. Im README.md ihres Repos dokumentieren Sie dieser (erste) Aufgabe rudimentär.

    10. Vergessen sie nicht, die nicht in das github-repo zu speichernden Dateien zu exkludieren.

    11. Für jeden Endpoint ist ein Commit mit einer aussagekräftigen Message zu erstellen.

    12. Abgabe bis 12.Oktober 2020, 23:59

    13. Den Link zum Classroom-Repository finden Sie im Discord.

Verwenden Sie eine Stammdatenklasse.
____   ____.__       .__    ___________        _____      .__
\   \ /   /|__| ____ |  |   \_   _____/_______/ ____\____ |  |    ____
 \   Y   / |  |/ __ \|  |    |    __)_\_  __ \   __\/  _ \|  |   / ___\
  \     /  |  \  ___/|  |__  |        \|  | \/|  | (  <_> )  |__/ /_/  >
   \___/   |__|\___  >____/ /_______  /|__|   |__|  \____/|____/\___  /
                   \/               \/                         /_____/

6. 2020-10-13

6.1. Testen Allgemein

  • Unterschied

    • Unit Test

    • Integration Test

  • TDD

  • Coverage

    • Wie viel macht Sinn

      • Happy Path & Edge Cases

      • Was muss man eventuell nicht automatisiert(!) testen

    • mehrere mögliche Programmläufe durch Verzweigungen

6.2. Quarkus Tests

  • Besprechung was im Hintergrund eigentlich alles passiert

  • Syntax (& Packages)

  • Was sollte man damit testen

  • Tests gemeinsam erstellt für:

    • Statuscode

    • Body Content

7. Benotung Assignment 1 - Entities mit CRUD - Funktionalität

Noten sind (demnächst) im Moodle-Kurs abrufbar.

Bewertung Assignment 1 - Download am 2020-10-14 11:42
lfd.Nr. Name Kommentar Note

1

BM

  • Thema: Friedhofsverwaltung

  • nicht lauffähig

  • keine Endpoints

  • das heißt nicht cementry, sondern CEMETERY oder GRAVEYARD

  • Dir fehlen sämtliche Projektdateien (mvnw, pom.xml, .gitignore, …​)

  • Felder in einer Klasse sind private (→ Geheimnisprinzip)

    public class Person {
    
        Integer id;
        String name = "";
        LocalDateTime bday;
        String causeOfDeath = "";
    
        public Person(Integer id, String name, LocalDateTime bday, String causeOfDeath) {
            this.id = id;
            this.name = name;
            this.bday = bday;
            this.causeOfDeath = causeOfDeath;
        }
        //...
    }
    • besser wäre eine Entität Grab(grave), die ist wohl am Wichtigsten (mit einem Feld Ansprechperson (contact))

    • Person ist schon ok, aber erst später. BTW: Die Todesursache geht keinen was an (ev. auch hier eine Kontaktperson i.S.v. Kunde)

ngd(5)

2

DJ

  • Thema: Produktionsbetrieb (Fließband)

  • sehr ausführliche Dokumentation im README.md

  • .gitignore

    • Wenn Du den gesamten .idea-Ordner ausschließt, verlierst Du auch jedes mal Deine Datasources etc

    • besser ist es, nur workspace.xml auszuschließen

  • PATCH fehlt

  • employee.http hat falsche urls

Bravo

sgt(1)

3

DF

  • Thema: Centermanager

  • Einen Schönheitspreis gewinnt Dein Algorithmus nicht dumfarth string concat

    • StringBuilder?

    • sprechende Methodennamen: hello(…​) ?

  • Du hättest ev. auch mal einen Objekttyp (Entityklasse) als Parametertyp nehmen können

  • Wenn Du sowieso nur ein JsonObject erwartest, dann kannst Du ruhig JsonObjekt als Datentyp nehmen und nicht immer JsonValue

  • Bei einem REST-Endpoint keine Webseiten zurückgeben (auch wenn es gut aussieht) → Stichwort: maschinenlesbar dumfahrt get

    • Für Webseiten kannst Du index.html verwenden

    • besser JSON, XML, …​

  • Testdaten → Bravo

sgt(1)

4

EQ

  • Thema: Baustellenkoordinator

  • sehr aufmerksam → XmlLocalDateAdapter

Implementierung des XmlAdapters
import javax.xml.bind.annotation.adapters.XmlAdapter;
import java.time.LocalDate;

public class XmlLocalDateAdapter extends XmlAdapter<String, LocalDate> {


    @Override
    public LocalDate unmarshal(String s) {
        return LocalDate.parse(s);
    }

    @Override
    public String marshal(LocalDate localDate) {
        return localDate.toString();
    }
}
Verwendung des XmlAdapters
@XmlRootElement
public class Construction {
    // ...
    @XmlJavaTypeAdapter(value = XmlLocalDateAdapter.class)
    public void setDeadLine(LocalDate deadLine) {
        this.deadLine = deadLine;
    }
    // ...
}
  • Response beim POST nicht korrekt, aber fast

POST http://localhost:8080/constructions

HTTP/1.1 201 Created
Content-Length: 0
Location: http://localhost:8080/constructions  (1)

<Response body is empty>

Response code: 201 (Created); Time: 28ms; Content length: 0 bytes
1 hier sollte die Resource des Elements stehen
ConstructionService
@Path("/constructions")
public class ConstructionService {
    //...
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response create(Construction construction, @Context UriInfo uriInfo) {
        ConstructionRepository
                .getInstance()
                .create(construction);  (1)

        return Response.created(uriInfo
                .getAbsolutePathBuilder()
                 //.path(Integer.toString(id))
                .build())
                .build();
    }
    //...
}
1 hier wäre die Rückgabe des Schlüssels vorteilhaft, der dann in die Location hinzugefügt werden kann (siehe auskommentierten Code).
  • Git-Commits ok

sgt(1)

5

EP

  • Thema: Baumschule

  • gut in README.md dokumentiert

  • Aktueller Quarkus 1.8.1

  • leider keine vollständige CRUD-Funktionalität

bef(3)

6

FS

  • Thema: Kochrezepte

  • Die geborene Köchin feichtinger putenschnitzel

  • Für die Parameter gilt das selbe wie bei Felix

  • Für Deine Algorithmen gilt ebenfalls exakt dasselbe wie bei Felix

  • Testdaten → Bravo (ebenfalls wie bei Felix)

sgt(1)

7

FJ

  • Thema: Farmverwaltung

  • Tolle Farmverwaltung

Product.java
package at.htl.fitzinger_farmverwaltung.entity;

public class Product {
}
ProductService.java
package at.htl.fitzinger_farmverwaltung.boundary;

public class ProductService {
}
ProductRepository.java
package at.htl.fitzinger_farmverwaltung.entity;

import java.util.ArrayList;

public class ProductRepository {
    ArrayList<Product> products = new ArrayList<Product>();
}

ngd(5)

8

HT

  • Thema Optiker

  • nur leere Klassen

package at.htl.hoefler_optiker.entity;

public class Product {
}
package at.htl.hoefler_optiker.entity;

import java.util.ArrayList;

public class ProductRepository {
    ArrayList<Product> productList = new ArrayList<Product>();
}

ngd(5)

9

KS

  • Thema: Facility Management

  • Sehr witzig, wo sind die ganzen maven-Files? kalinke project contents

    klausner leeres repo

  • Warum gibst Du immer eine Liste zurück?

public class BuildingRepository {

    private final List<Building> buildings = new ArrayList<>();

    //...
    public List<Building> addEntity(Building building) {
        buildings.add(building);
        return buildings;
    }

    public List<Building> removeEntity(Building buildingToRemove) {
        for (Building buildingEntry : buildings) {
            if (buildingEntry.getType().equals(buildingToRemove.getType())) {
                buildings.remove(buildingEntry);
                return buildings;
            }
        }
        return buildings;
    }
    //...
}
  • Das ist keine CRUD-Funktionalität (nur GET)

    kalinke crud

gen(4)

10

KF

  • Thema: Zooverwaltung

  • leider leeres Repo abgegeben

ngd(5)

11

KS2

  • Thema: Event-Manager

  • völlig leer, nicht mal ein leeres Projekt

ngd(5)

12

MR

  • Thema: Reisebüro

  • .gitignore → siehe Dorfinger

  • http://localhost:8080/reise → siehe Dumfarth

    • Ist cool gelöst, mit den unterschiedlichen MIME-Types

sgt(1)

13

MA

  • Thema: Plattenlabel

  • nur 2 leere Klassen (Label und Mitarbeiter)

  • Anmerkung: Klassen sollten englisch benannt werden

ngd(5)

14

OJ

  • Thema: Tanzschule

  • Im jonasoirer-Repo hast Du ein Verzeichnis oirer-tanzschule, in dem man dann das Projektverzeichnis oirer-tanzschule findet. → Das ist eindeutig zu tief verschachtelt

    oirer folder structure

  • Beim Repository ist eine Datenelement einzufügen (add), nicht die bestehende Collection durch eine andere zu ersetzen (set)

    public class DancingRepository {
    
        private List<DancingTeacher> repository = new ArrayList<>();
    
        public DancingRepository() {
            setRepository();
        }
    
        private void setRepository() {
            repository.add(new DancingTeacher(1, "Jonas", "Oirer"));
            repository.add(new DancingTeacher(2, "Aleks", "Vidakovic"));
        }
    
        public List<DancingTeacher> getRepository() {
            return repository;
        }
    
        @Override
        public String toString() {
            return "DancingRepository{" +
                    "repository=" + repository +
                    '}';
        }
    }
    • Man kann nichts hinzufügen

    • Man kann nichts löschen

    • Man kann nichts ändern

    • Man kann kein einzelnes Datenelement abrufen

  • Deine Packages und Klassen sind unstrukturiert oirer packages

    • in das Package entity gehören nur entity-Klassen, keine Endpoints und auch kein Repository

  • openapi / swagger sind NICHT installiert

  • dein request.http ist

    • unvollständig und

    • fehlerhaft (PUT ohne body)

  • Was ist da nicht optimal?

    @Path("/dancer")
    public class DancingTeacherService {
        @GET
        @Produces(MediaType.TEXT_PLAIN)
        public String hello() {
            return "hello oiropean dancers!";
        }
    
        private String coolestTeacher;
    
        @PUT
        @Path("coolest")
        @Consumes(MediaType.APPLICATION_JSON)
        public String getCoolestTeacher(DancingTeacher dancingTeacher) {
            this.coolestTeacher = dancingTeacher.getFirstName();
            return String.format("%s is the best", this.coolestTeacher);
        }
    }
  • Routen sollten nie im camel-Case sein, sondern kebab-case

gen(4)

15

PV

  • Thema: Skischule

  • sehr umfangreich

sgt(1)

16

RJ

  • Thema: Fitnessstudio

  • leider nur ein leeres Projekt abgegeben

ngd(5)

17

SS

  • Thema: Fakturierung

  • Die Bezeichner (der Klassen) sollten englisch sein

  • Die Requests funktionieren nur im JSON-Format. Nicht wie in der Angabe gefordert auch im XML-Format

sgt(1)

18

SL

  • Thema: Kfz-Händler

  • Sehr umfangraich und sauber

  • Ein Datum wäre gut gewesen

sgt(1)

19

SM

  • Thema Friseurladen

  • das kann wohl nicht funktionieren!

    • Wo wird der bodey des requests eingelesen

    • keine Groß-/Kleinschreibung bei Routen

    • Du legst bei jedem Request ein eigenes Repository an (?!)

@Path("/person")
public class FriseurService {
    //...
    @POST
    @Path("/friseurJSON")
    @Produces(MediaType.APPLICATION_JSON)
    public List<Friseur> getFriseurList(){
        if (repository.friseure.size()== 0) {
            repository.createRepository();
        }
            return repository.friseure;
    }
    //...
}

bef(3)

20

TS

  • Thema Restaurant

  • beim POST muss man sicherstellen, dass bei mehrmaligen ausführen das Element nur einmal hinzugefügt wird

  • es ist aber sehr sauber programmiert

sgt(1)

21

TK

  • Thema: Callcenter

  • Dir fehlen sämtliche Projektdateien (mvnw, pom.xml, .gitignore, …​)

  • Die Klassennamen sollten immer in Englisch sein (alle Bezeichner)

  • CRUD nicht vollständig implementiert

  • nicht lauffähig

gen(4)

22

TI

  • Thema: Busreisen (inkl Schulbusse)

  • Grundsätzlich sehr sauber

  • Es sollte auch möglich sein, nur einzelne Elemente zu lesen

  • Warum ist beim GET nur XML möglich?

  • Du solltest packages verwenden

  • git commits sind ok

gut(2)

23

WN

  • Thema Autovermietung

  • Image-Links in README.md broken

  • git-kommentar "zwischencommit" ist nicht sehr sprechensd

  • Man sollte ein Element nur einmal posten können

    • beim POST muss man sicherstellen, dass bei mehrmaligen ausführen das Element nur einmal hinzugefügt wird

sgt(1)

24

WJ

  • Thema Parkplatzverwaltung

  • ad README.md → Du solltest Dir wirklich ansehen, wie man images in markdown files verlinkt

  • Du Minimalist

sgt(1)

Kriterien
  • Das Projekt muss lauffähig sein (am Besten in ein neues Verzeichnis clonen und ausprobieren)

  • Testdaten sind sehr hilfreich

Allgemeine Bemerkungen
  • Bezeichner in englisch (ist so üblich)

  • ist eine List wirklich die geeignete Collection für das Repository

  • der erste url einer RESTful-API sollte /api sein (ebenfalls sehr oft üblich)

Was ist zu tun
  • Fehlerbehandlung → WebException

  • Wie sind die Responses aufgebaut?

  • Kalenderdatum als Parameter bzw Datenbestandteil

8. 2020-11-06 CDI - Context and Dependency Injection

  • Scope …​ (Gültigkeits-)Bereich

    • zB Gültigkeitsbereich bei Variablen (i.N. ein Block)

    • zB Lebensdauer von Objekten (ApplicationScoped, SessionScoped, RequestScoped)

    • …​

  • CDI

    • C …​ Context …​ Lebensdauer der Objekte

    • DI …​ Dependency Injection …​ Injizieren einer Abhängigkeit

  • Was bringt CDI?

    • Inversion of Control / IoC: Das Programm muss sich nicht mehr um die Erstellung von Objekten kümmern, das übernimmt der Container

    • Dies führt zu wenig fehleranfälligen Programmen

      • Um Erstellen/Zuweisen/Löschen der Objekte kümmert sich der Container

      • Man kann einfach die Konfiguration ändern

        • Testcontainer mit Testobjekten

        • Produktiv-Containe mit Real-Life-Objekten

  • Dependency

    • Eine Dependency oder Abhängigkeit beschreibt in der Softwareentwicklung, dass ein Programm ein bestimmtes Stück Code (z. B. Frameworks, Bibliotheken, Klasse) benötigt, um ordnungsgemäß zu funktionieren.

  • Wie kann ein Objekt erstellt werden?

    • Durch Verwendung des Schlüsselwortes new

    • Durch Verwendung von Design Patterns (Entwurfsmuster)

      • zB einer Factory (Design Pattern)

      • zB eines Builder Pattern (Erbauer)

    • Durch Dependency Injection

Objekterstellung mit "new"

object creation with new

  • Erstellt man ein Objekt mit "new", so ist man selbst für die Lebensdauer verantwortlich

    • Man kann das obige Person-Objekt löschen, indem man die Referenz auf das Objekt löscht

    • Der Garbage Collector gibt den Speicherpaltz des Objekts frei.

Durch NULL-setzen der Refernzvariablen wird der Speicherplatz freigegeben.

objcect deletion

  • Bei CDI ist der sogenannte DI-Container verantwortlich für

    • das Erstellen von Objekten

    • das Zuweisen zu einem Context (Lebensdauer)

    • das Zuweisen von Objekten zu Variablen

    • das Löschen von Objekten (Freigeben des Speicherplatzes)

    • man spricht von "container-managed" Objekten oder auch Java-Beans

    • Durch Verwendung von Annotation (@ApplicationScoped, @SessionScoped, @RequestScoped) kann man die Lebensdauer beeinflussen.

    • Mit @Inject kann der Developer eine Instanz einer Klasse anfordern.

  • The container is the environment where your application runs.

  • Was ist ein Servlet

    • Ein Servlet ist DIE Methode, um Java-Code aus dem Internet (mittels TCP/IP)) aufrufen zu können

    • Viele Bibliotheken zB JAX-RS, JSF usw verwenden im Hintergrund Servlets.

8.1. Logging in Jakarta EE (Quarkus)

  • Es wird empfohlen den jboss-Logger zu verwenden.

@ApplicationScoped
public class GreetingService {

    private static final Logger logger = Logger
            .getLogger(GreetingService.class.getSimpleName()); (1)

    int counter;

    public String greeting(String name) {
        logger.info(String.format("Hello %s (%d x verwendet)", name, ++counter)); (2)
        return String.format("Hello %s (%d x verwendet)", name, ++counter);
    }
}
1 Man muss einen Logger deklarieren. Der Klassenname wird übergeben.
2 Man kann den Logger verwenden
Output des Loggers in Console
2020-11-06 09:40:53,795 INFO  [at.htl.con.GreetingService] (executor-thread-198) Hello susi (1 x verwendet!)
  • Es gibt Log-Levels

    • INFO

    • ERROR

    • FATAL

    • DEBUG

    • …​

  • Es gibt sogenannte Appender zur Ausgabe auf verschiedenen Medien

    • Konsole

    • in Text-Files (auch rotierend)

    • in Datenbanken

    • auf einen REST-Endpoint

    • …​

8.1.1. Logging mit Dependency Injection

Man kann auch einen Logger mit DI injizieren

Erstellen des Producers
public class LoggerProducer {

    @Produces
    public Logger produceLogger(InjectionPoint injectionPoint) {
        return Logger.getLogger(injectionPoint.getBean().getBeanClass());
    }
}
Verwendung des injizierten Loggers
@ApplicationScoped
public class GreetingService {

    @Inject
    private Logger logger; (1)

    int counter;

    public String greeting(String name) {
        logger.info(String.format("Hello %s (%d x verwendet!)", name, ++counter)); (2)
        return String.format("Hello %s (%d x verwendet!)", name, ++counter);
    }

}
1 Die Logger Klasse wird injiziert.
2 Die Verwendung bleibt gleich

8.2. Offene Punkte

  • Warum funktioniert CDI nicht im Constructor?

  • Was kann ich machen, um trotzdem CDI bei der Erstellung von Objekten zu verwenden? → @PostConstruct

  • Autostart in Quarkus-Apps (@Observer)

9. 2020-11-13

9.1. Testen

testing

V-Modell

v modell

9.2. restAssured + assertJ

  • Vocabulary

    • specification …​ techn. Beschreibung

    • validieren …​ auf Gültigkeit überprüfen

    • verifizieren …​ auf Korrektheit überprüfen

    • route …​ der Pfad in der URI nach dem Host und dem Port

request reponse structure

9.2.1. GET-Request

  • Es wird automatisch localhost:8080 verwendet

  • Alternative: .when().get("http://localhost:8080/person")

    @Test
    public void testPersonEndpoint() {
        var person =
            // arrange
            given()
            // act
            .when().get("/person")
            // assert -> Rückgabe überprüfen
            .then()
                .statusCode(200)  // wir validieren
                .extract()
                   .body()
                   .as(Person.class);
        assertThat(person).isNotNull();
        assertThat(person.getName())
                .isNotNull()
                .isNotEmpty()
                .isEqualTo("Sepp");
    }

9.2.2. POST-Request

    @Test
    public void testPostPersonEndpoint() {

                given()
                // arrange
                   .contentType(ContentType.JSON)
                   .body(  // Text Blocks (1)
                       """
                        {
                          "vorname":"Markus",
                          "nachname":"H"
                        }
                        """)
                   // act
                   .when().post("/person/jsontype")
                   .then()
                   .statusCode(200);  // wir validieren
    }
1 Verwendung von Text-Blocks ab Java 15 (→ pom.xml)
bis Java 14
.body("{\"vorname\": \"Markus\", \"nachname\": \"H\"}")

9.3. Startup-Methode in Quarkus

  • wird nach dem Start der Applikation ausgeführt.

@ApplicationScoped
public class InitBean {

    // vergleichbar mit main()-MEthode
    void onStart(@Observes StartupEvent event) {
        LOG.info("The application is starting ...");
    }

}

9.4. PostConstruct-Methode

  • Man kann injizierte Resourcen (Objekte) im Konstruktor nicht verwenden, da sie erst nach der Ausführung des Konstruktors injiziert werden.

@ApplicationScoped
public class InitBean {

    @Inject
    GreetingService greetingService;

    public InitBean() {
        // hier kann man greetingService noch nicht verwenden
    }

    @PostConstruct
    private void init() {  (1)
        greetingService.greeting("Jonas 1");
    }
}
1 Diese Methode wird ausgeführt:
  • nachdem das Objekt fertig gebaut ist (der Konstruktor wurde bereits ausgeführt)

  • nachdem die Resourcen injiziert wurden → daher kann man diese Resourcen auch hier verwenden

9.5. Verwendung einer Datenbank

  • Persistierung mit JPA

10. 2020-11-13

10.1. Vorgangsweise beim Einrichten

zB Die Objekte einer Klasse Person sollen in einer DB persisitiert werden

  • Bibliotheken zur pom.xml hinzufügen

    • zB Hibernate / JPA

    • JDBC-Treiber der Datenbank (postgres-jdbc-driver)

  • Einrichten der zugangsdaten in application.properties

    • jdbc-url

    • username

    • password

  • Datenbank einrichten und starten

    • zB mit Docker

  • Entity-Klasse Person vorbereiten

    • @Entity als Klassen-Annotation

    • Long id hinzufügen mit Annotation @Id

    • Ev. einer Id-Generator annotieren

      • 3 Strategien (AUTO ist keine eigene Strategie)

      • TABLE

      • IDENTITY

      • SEQUENCE

      • AUTO

  • Injizieren Eines EntitiyManagers

  • Bei schreibenden Operationen Annotation @Transactional verwenden.

Voíla …​ jetzt kann man persistieren

11. 2020-11-17 - Forts. JPA mit Quarkus

11.1. DB Setup

Wir verwenden als Beispiel Postgres (weil open source, sehr verbreitet und flexibel).

DB herdockern
docker pull postgres
docker run --name postgres --rm -e POSTGRES_PASSWORD=postgres -d -p 5432:5432 -v $HOME/databases/postgres:/var/lib/postgresql/data postgres

Anschließend die db anlegen (create database quarkdb).

11.2. Project Config

Zwei Dependencies:

  • io.quarkus:quarkus-hibernate-orm

  • JDBC driver (z.B. quarkus-jdbc-postgresql)

Hinzufügen via 'add with maven' Command von der https://code.quarkus.io website.

DB Connection konfigurieren
# datasource configuration
quarkus.datasource.db-kind = postgresql
quarkus.datasource.username = postgres
quarkus.datasource.password = postgres
quarkus.datasource.jdbc.url = jdbc:postgresql://localhost:5432/quark-db

# drop and create the database at startup (use `update` to only update the schema)
quarkus.hibernate-orm.database.generation=drop-and-create

11.3. Entity anlegen & verwenden

  • Entities annotieren (@Entity, @Id,…​) (s.o.)

    • Serialisierungsoptionen für enum

    • Relationen (1:1, 1:n, m:n) entsprechend abbilden

      • Angabe des Foreign Key

      • Cascade Optionen

  • Repository in Service injecten

  • EntityManager in Repository injecten

  • Service Methode mit @Transactional annotieren

    • Im Service und nicht im Repo, weil wir ggf. mehrere Operationen zusammenfassen!

      • LUW!

11.4. Queries

  • Abfragen werden mit JPQL erstellt

    • Ähnlich SQL aber mit Abwandlungen/Erweiterungen wie:

      • Joins über Referenzen "implizit" möglich

      • Objekte (new) können angelegt werden

      • Abfragen auf Class- und nicht auf Tablename

      • …​

    • Placeholder (prepared statement) zwecks SQL Injection Vermeidung

  • Zwei Optionen:

    • (Typed)Queries direkt über den EntityManager erstellen

    • NamedQueries in der Entity class definieren

  • Laden verbundener Entitäten:

    • Lazy Loading

    • Eager Loading

12. Strategien für Primärschlüsselerstellung

  • IDENTITY

    • Autowert, AutoIncrement → in einem Tabellenfeld wird automatisch ein Zähler hochgezählt

  • SEQUENCE

    • Die Sequence ist ein eigenständiges Datenbankobjekt, die eine Folge von Zahlen generiert

    • in Reihenfolge, zufällig, rollieren usw.

    • kann man mit der Annotation @SequenceGenerator im Code erstellem

  • TABLE

    • die einfachste Variante

    • eine Tabelle (meist mit Namen SEQUENCE) hat ein Feld mit einer Zahl, die mit UPDATEs hochgezählt wird

    • Manchmal hat man für jede Tabellen-Id eine eigene Zeile

  • AUTO

    • eine der obigen Staretgien wird automatisch gewählt (meist TABLE)

13. 2020-11-17

Prof. Haslinger

13.1. Persistieren mit Enums und Referenzen zwischen Klassen

@Enumerated(EnumType.ORDINAL) (1)
private Gender gender;
1 Der enum Wert wird als String in DB gespeichert

13.2. Fetching EAGER vs LAZY

13.3. Bidirektionale Beziehungen

bidirect
  • Problem: wird ein Hobby in hobbies eingetragen,

Wird in in einem Hobby-Objekt eine Person eingetragen
public void setPerson(Person person) {
    this.person = person;
    person.getHobbies().add(this); (1)
}
1 Man aktualisiert

14. 2020-12-01

14.1. Datenmodell

14.2. Test

  • zuerst Use-Cases / User-Stories definieren und dann

  • Tests für die einzelnen Use-Cases / User-Stories schreiben

    • System-Tests (Endpoints)

      • zB ein Produkt anlegen

      • zB einen Kunden anlegen

      • zB eine Rechnung mit drei Rechnungspositionen erstellen

    • Integrations-Tests (zB für Repository-Klassen)

      • vor allem Dingen die Assoziationen

        • unidirektional

        • wenn bidirektional, das Einfügen und löschen von Objekten AUF BEIDEN SEITEN

    • Unit-Tests (nur eine Klasse wird getestet, zB Entity-Klassen)

      • nicht nur Getter und Setter testen

      • eher eigene Logik (wenn etwas berechnet wird, equals-Methoden usw.)

      • wenn ein Setter/Getter eine beondere zusätzliche Logik hat, dann ist er sehr wohl zu testen

14.3. Arten von Beziehungen zwischen Objekten

14.3.1. Vererbung

vererbung
Pkw kaefer = new Pkw();
  • 3 Strategien

    • SINGLE_TABLE

    • TABLE_CLASS (table per concrete class)

    • joined

14.3.2. Aggregation

  • besteht-aus, consists-of

  • Objekte können zerstörungsfrei getrennt werden

  • Bsp: Auto und Autoreifen

aggregation

14.3.3. Komposition

  • besteht-aus, consists-of

  • Objekte können nicht zerstörungsfrei getrennt werden

  • Bsp

    • Buch - Kapitel

    • Haus - Etage

komposition

14.3.4. Assoziation (<use>-Beziehung)

in verschiedenen Multiplizitäten (Kardinalität)

  • 1:*

  • 1:1

  • *:*

assoziation

14.4. UML-Klassendiagramm

cld01
  • Konvention → Vereinbarung

  • Signatur einer Methode: Scope + Rückgabewert + Methodenname + Parameterleiste

  • Objekt (Object) = Instanz einer Klasse; mit Identität und Zustand

  • Beispiel: PKW

    • Anwendungsfall 1: Transport von Personen

    • Anwendungsfall 2: Transport von Gütern

    • Anwendungsfall 3: Cruisen auf der Landstraße (Statussymbol)

  • Eigenschaften von Objekten

    • Objektidentität

objektidentitaet

  • Datenkapselung datenkapselung

  • Polymorphismus (Vielgestaltigkeit)

polym
Duck donald = new Duck();
donald.say(); // quack
Cat mimi = new Cat();
mimi.say(); // miau

List<Animal> animals = new LinkedList<>();
animals.add(donald);
animals.add(mimi);
animal.get(0).say(); // quack
annimal.get(1).say(); // miau
  • Vererbung

14.4.1. Beziehungen zwischen Objekte

Generalisierung (Vererbung)
Assoziation
assoziation01
assoziation02
Figure 1. unidirektional
assoziation03
Figure 2. unidirektional
assoziation04
Figure 3. bidirektional
Beispiel: Automatisch ergänzen der anderen Seite
public class Person {
    public void setFirma(Firma firma) {
        if (firma != null && firma.isInstanceof(Firma.class)) {
          firma.addPerson(this);
        }
    }
}
Aggregation
  • "Ganze-Teile"-Beziehung, die zerstörungsfrei zerlegt werden kann

  • Bsp

    • Auto + Autoreifen

Komposition
  • "Ganze-Teile"-Beziehung, die nicht zerstörungsfrei zerlegt werden kann

  • Bsp

    • Haus + Stockwerk

    • Buch + Kapitel

15. 2020-12-15

select c.CUST_COUNTRY, count(*)
from SW_CUSTOMER c
inner join SW_ORDERING SO on c.CUST_ID = SO.ORD_CUST_ID
group by c.CUST_COUNTRY;
select o.customer.country, count(o) from Ordering o group by o.customer.country
  • Bei Verwendung von JPA kann man sich den Join sparen, da eine Assoziation existiert.

16. 2021-01-15

16.1. Panáche

siehe Quarkus-Lecture-Notes

bis Repository-Pattern (Bsp wurde erstellt)

16.2. Unterschied Spezifikation - Implementierung

16.2.1. Spezifikation

zB. JPA oder Jakarta Persistence

16.2.2. Implementierung

zB EclipseLink, Hibernate

16.3. Begriffe

  • Surrogat …​ Ersatz

  • Ist ein Ersatz für einen natürlichen Schlüssel in einer relationalen DB.

  • Ist ein künstlicher Schlüssel (Primary Key).

    • Meist eine lfd. Nr., die von der DB hochgezählt wird.

  • Begriffspaar transient/persistent

    • transient …​ flüchtig

    • persistent …​ dauerhaft (die Daten überleben den Prozess ihrer Entstehung)

  • custom (im Gegensatz zu vorgegeben/vordefiniert/standardisiert)

    • custom …​ maßgeschneidert, der Benutzer kann sich etwas eigenes "bauen"

  • Referenz

    • Verweis auf etwas

    • Beispiele

      • Referenzvariable verweist auf ein Objekt (refernziert ein Objekt)

      • Kundenreferenz verweist auf (hoffentlich zufriedene) Kunden meines Produkts

      • Referenzen in meinem Lebenslauf: verweisen auf vorhergegangene Arbeitgeber (die hoffentlich auch zufrieden waren)

17. 2021-01-19

17.1. Panache

Live-Coding-Projekt: panache-person-demo

  • Custom Id

  • detached / attached

  • UnitTest erstellt

  • Unterschied @QuarkusTest und ohne Annotation

  • Panache methods

    • find mit Sort.by()

    • paging

  • Übung: Erweiterung des Microprojektes mit sinnvollen panache …​

  • Übung 2:

    • Vorbereiten des Codes, um in einem Endpoint, die einzelnen Seiten als JSON auszugeben

  • Für Spezialisten: Verwendung von Qute, um Die Seiten als HTML gerendert auszugeben.

18. 2021-01-21 - Angular

18.1. Angular Übungen

Angabe Fällig

Turmrechnen

TODO Liste

23.03.

Zahlen Raten

06.04.

Wiederverwendbare Charts

20.04.

Simple Survey

11.05.

Simple Survey & Router

25.05.

Simple Survey & Server

01.06.

19. 2021-01-26

  • Was ist ein:

    • HTML - Element

    • HTML - Attribute

    • HTML - Tag

  • format …​ das aussehen betreffend

    • zB Aussehen eines Word - Dokuments (fette Schrift, Schriftart, …​)

    • zB die Datenstruktur: als JSON formatieren

  • to render …​ für die Ausgabe vorbereiten

20. 2021-02-05

  • Chapter 4. Templates and Data Binding

    • 4.1. Interpolation

    • 4.2. Event-Binding

    • 4.3. Template Expressions

    • 4.4. Property Binding

    • 4.5. Two-Way-Binding

    • 4.6. Structural Directive - *ngFor

    • 4.7. Event with Parameter

    • 4.8. Structural Directive - *ngIf

    • 4.9. Exercise: Turmrechnen

21. 2021-02-16

After every unit commit into repo: https://classroom.github.com/a/_WHf3y1Q
each commit has to include your last name - ie Mueller - unit 1 / 1 Introduction to Angular
For every angular-project use an own branch
Never ever push node_modules into your git-repo
use -g when creating a new angular project, to avoid a mess with the git-repos
Web-Frontends and Backend

web frontends and backend

21.1. SPA - Single Page Application

22. 2021-02-23

23. 2021-02-19

bis exklusive 5.2.4 Output Events

24. 2021-02-23

dom

25. 2021-02-26

bis exkl. 5.3. Exercise: Einheitenumrechner

26. 2021-03-02

27. 2021-03-09 (Gr.2)

  • LZK02

Kap. 6 Accessing Web APIs

accessing web api

28. 2021-03-16

  • Übung Zahlen Raten

  • Vereinbarung

    • Tour of Heroes bis zum nächsten mal

      • bis inkl. Kapitel 4: Services

webapi
  • TODO: REST-Client in Angular-Technology-Notes überarbeiten

29. 2021-03-23 - Gr B

  • Services wurden besprochen

30. 2021-03-26 - Distance Learning

HTML-Attributes vs. DOM-properties

html attibutes vs dom prperties

  • Nach den Ferien ist die Gruppe A anwesend

  • Bis nach den Ferien ist das Tutorial "Tour of Heroes" fertigzustellen (Gr. A + Gr. B)

    • Download der Repositories am 9. April 2021 → wird bewertet

31. 2021-04-09 (Fr.) - HttpClient & Routing

rest overview

rest jsonb jsonp

32. 2021-04-13

  • FIT (Firmeninformationstag)

  • Routing wurde besprochen

    • Warum?

    • jedoch nicht implementiert

  • Das microprojekt ist zu erstellen

    • Entities

    • Repositories

    • restful Services

33. 2021-04-16 Routing

  • Bsp. route-demo

  • Beim microproject ist routing einzubauen

34. 2021-04-20 - Gruppe A

35. 2021-04-22 - Distance Learning

35.1. synchronous vs asynchronous

angular blocking nonblocking

35.2. How to program asynchronous?

angular async programming

35.3. System Architecture

angular async services

36. 2021-05-11

37. Konkretisierung der Angabe für das Mikroprojekt

  • Das Microprojekt besteht aus zwei Teilen:

    • Backend (Quarkus / JakartaEE)

    • Frontend (Angular)

  • Zuerst ist das Backend sauber zu erstellen (Ordner backend im Repository)

    • Die Tabellen und deren Assoziationen müssen korrekt sein und mind. der 3.NF entsprechen

    • Es sind Endpoints zu erstellen:

      • Bei den Endpoints dürfen nicht nur die Daten jeweils einer Entität (Tabelle) zurückgegeben werden, sondern es ist mindestens eine Query zu erstellen, die aus mehreren Tabellen Daten zurück gibt.

      • Auch sind die Werte zu filtern:

        • zumindest einmal mit QueryParams

        • zumindest einmal mit PathParams

      • Mindestens ein Endpoint muss

        • einen GET-Request

        • einen POST-Request

          • einmal mit nur einem Objekt und

          • einmal mit mehreren Objekten

        • einen PUT-Request

        • einen PATCH-Request

        • und einen DELETE-Request beinhalten

    • Es ist zumindest ein request.http - File im http-requests - Ordner zu erstellen, damit die Abfrage der Endpoints dokumentiert ist

    • In der README.md ist eine sehr rudimentäre Dokumentation enthalten:

      • Datenmodell

      • Use-Case mit UCD: Es sind spezielle Use-Cases für das jeweilige Thema zu implementieren

        • zB für ein Kino die Sitzreservierung bei Filmen

        • es darf nicht für jede Themenstellung eine User-, Kunden- oder sonstige Verwaltung durchgeführt werden, die bei sämtlichen Themenstellungen ident ist.

      • Infos über die Endpoints - dies kann und soll durch einen Swagger ersetzt werden → Link auf Swagger angeben

      • Die Default-Swagger-Infos können und sollen durch Annotationen ergänzt werden.

      • Die Angabe soll als Checkliste angegeben sein, damit auf einen Blick ersichtlich ist, was gemacht wurde.

      • Wie startet man das Projekt.

Es geht grundsätzlich nicht darum, dass alle Endpoints (dh für alle Entitäten) vollständig ausprogrmmiert werden. Allerdings sind die verschiedenen Konzepte (Queries, Params, Request-Arten, POSTs mit einem und mehreren Objekten als csv oder json) einmal zu implementieren.
  • Das Frontend wird später erstellt.

  • Abgabetermin: 25. Mai 2021, 8:00

  • Als Repo wird 17-microproject verwendet

38. 2021-05-25

39. 2021-06-01 - Quarkus Recap

40. 2021-06-04 - Quarkus Recap

Stati eines Objects in JPA (Source: stackoverflow)

jpa stati

Entity can become detached in one of the following ways (there could be more ways):

  • When the transaction (in transaction-scoped persistence context) commits, entities managed by the persistence context become detached.

  • If an application-managed persistence context is closed, all managed entities become detached.

  • Using clear method

  • Using detach method

  • rollback

  • In extended persistence context when a stateful bean is removed, all managed entities become detached.

Source: stackoverflow


  • Teststoff:

    • JPA / Panache

    • Jax-RS

      • Params: FormParam, PathParam, QueryParam, …​

    • JSON-B

    • JSON-P

    • Dateizugriff

    • Arbeiten mit Strings, chars, …​

  • HTML/CSS/JS

  • properties-files