= Lecture Notes 4ahif - NVS 21/22 Thomas W. Stütz 1.0.0, {docdate}: Quarkus, Android Jetpack Compose ifndef::imagesdir[:imagesdir: images] //:toc-placement!: // prevents the generation of the doc at this position, so it can be printed afterwards :sourcedir: ../src/main/java :icons: font :sectnums: // Nummerierung der Überschriften / section numbering :toc: left //Need this blank line after ifdef, don't know why... ifdef::backend-html5[] // https://fontawesome.com/v4.7.0/icons/ icon:file-text-o[link=https://raw.githubusercontent.com/2122-4ahif-nvs/2122-4ahif-nvs-lecture-notes/main/asciidocs/{docname}.adoc] ‏ ‏ ‎ icon:github-square[link=https://github.com/2122-4ahif-nvs/2122-4ahif-nvs-lecture-notes] ‏ ‏ ‎ icon:home[link=https://htl-leonding.github.io/] endif::backend-html5[] // print the toc here (not at the default position) //toc::[] == 2021-09-28 * Quarkus Grundlagen (Foliensätze) == 2021-09-30 - entfallen == 2021-10-05 - entfallen wegen AHS-Vortrag == 2021-10-07, Do. image::request-response.png[] * REST-Clients * Testen in Quarkus (@QuarkusTest) == 2021-10-12, Di. image:v-modell.png[] [plantuml,vehicle-cld-1,png] ---- @startuml left to right direction class Customer { } class Vehicle { } Customer "*" -- "*" Vehicle : > entleiht (Customer, Vehicle) .. Rental @enduml ---- [plantuml,vehicle-cld-2,png] ---- @startuml left to right direction class Customer { } class Vehicle { } class Rental { Vehicle: vehicle Customer: customer LocalDate: dateFrom LocalDate: dateTo } Rental "*" --> "1" Vehicle : < wird entliehen Customer "1" <-- "*" Rental : > leiht @enduml ---- === Einteilung Mikroprojekte * Abazović Edina * Ablinger Raphael * Aichinger Niklas * Baumgartner Lukas * Bogdan Sebastijan * Handel Christoph * Hartl Anna * Hautzmayer Sheila * Hirsch Nico * Keintzel Florian * Kerschbaum Philipp * König Julia * Melcher Tamara * Neudorfer Niklas * Pavelescu Darius-Cristian * Pelzeder Joachim * Plakolb Marcel * Rathberger Jakob * Remplbauer Markus * Sugic Oliver * Tran Michael * Tunc Johannes == 2021-10-14 === REST Context === REST WebApplication Exception === JSON-B, JSON-P * https://javaee.github.io/jsonb-spec/users-guide.html === REST Parameter * QueryParam * PathParam * FormParam == 2021-10-18 (Einschub) image::jsonb-formparam.png[] image::hash.png[] image::mapping.png[] image::cors.png[] === Rest-Endpoints erstellt * FormParam * POST mit Location-Rückgabe === Mit JPA begonnen == 2021-11-04 image::ide-database-overview.png[] === 3 Strategien zur Erstellung der Schlüsselwerte ** Table ** IDENTITY ** Sequence === Transactions === Verwendung von Test zum Ausprobieren von DB-Zugriffen Begriffe: * ORM * JDBC * JAX-RS ** resteasy * JPA ** Hibernate == 2021-11-08 === Mögliche Fragen: * Welche Möglichkeiten gibt es, ein Quarkus Projekt zu erstellen? ** Assistent auf quarkus.io ** Assistent in IDE (zB IntelliJ) ** Aufruf mit mvn * Strategien zum Erzeugen von Primärschlüsselwerten? ** TABLE ** SEQUENCE ** IDENTITY * Wie kann man eine Testklasse für eine beliebige Klasse erstellen? ** Cursor auf Klassenbezeichnung ** Rechte Maustaste ** Create Test * Was bewirkt die Annotation `@QuarkusTest`? === Repositories für JPA https://docs.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/infrastructure-persistence-layer-design[The Repository pattern, window="_blank"] image::microsoft-repository-pattern.png[] === Startup * Die Methode init() wird sofort nach Start der Applikation ausgeführt (vglbar mit main()-Methode) * Die init()-Methode kann beliebig benannt werden [source,java] ---- package at.htl.carrental.control; import at.htl.carrental.entity.Person; import io.quarkus.runtime.StartupEvent; import javax.enterprise.context.ApplicationScoped; import javax.enterprise.event.Observes; import javax.inject.Inject; @ApplicationScoped public class InitBean { @Inject PersonRepository personRepository; void init(@Observes StartupEvent event) { Person p = new Person("Susi"); personRepository.save(p); } } ---- === Automatisches Befüllen der Tabelle mit IMPORT.sql * in Ordner `src/main/resources/` eine Datei `import.sql` erstellen: `src/main/resources/import.sql` * INSERTs einfügen * beim nächsten Start der App werden die INSERTs ausgeführt * https://quarkus.io/guides/hibernate-orm === NamedQueries * 2 Varianten ** JP-QL ** Criteria API (verwenden wir NICHT) .JP-QL (Java Persistence Query Language) [source,java] ---- @Entity @NamedQueries({ @NamedQuery( name = "Person.findAll", query = "select p from Person p" ) }) public class Person { //... } ---- * JP-QL ist vergleichbar mit SQL * jedoch werden i.N. keine SPalten angegeben, da nur ganze Objekte zurückgegeben werden. * die Rückgabe von Spalten ist sehr wohl möglich * Joins und Aggregationen sind ebenfalls möglich * https://www.objectdb.com/java/jpa/query/jpql/structure == 2021-11-09 === Ausführen einer NamedQuery [source, java,highlight=3-4] ---- @Test void getAllPersons() { TypedQuery query = em .createNamedQuery("Person.findAll",Person.class); List persons = query.getResultList(); assertThat(persons.size()).isEqualTo(8); logger.info(persons); } ---- === Ausführen einer Query [source,java,highlight=3-4] ---- @Test void getAllPersonsWithQuery() { TypedQuery query = em .createQuery("select p from Person p",Person.class); List persons = query.getResultList(); assertThat(persons.size()).isEqualTo(8); logger.info(persons); } ---- === Ausführen einer NativeQuery * Es gibt auch hier ** NativeQuery ** NativeNamedQuery [source,java] ---- @Test void getAllPersonsWithNativeQuery() { Query query = em .createNativeQuery("select p.id, p.name from person p"); List persons = query.getResultList(); for (Object[] elem : persons) { System.out.println(elem[0] + " " + elem[1]); } assertThat(persons.size()).isEqualTo(9); } ---- * https://thorben-janssen.com/jpa-native-queries/ === Mikroprojekte-Themen |=== |Name |Thema |Abazović Edina |Stadtrundfahrten |Ablinger Raphael |Linienbusunternehmen inkl. Fahrplan |Aichinger Niklas |Supermarkkt |Baumgartner Lukas |Teehändler |Bogdan Sebastijan |Friedhofsverwaltung |Handel Christoph |Schuhplattln |Hartl Anna |Gärtnerei |Hautzmayer Sheila |Tanzverein |Hirsch Nico |Rezeptseite |Keintzel Florian |Hotel |Kerschbaum Philipp |Fussballverein |König Julia |Tennisverein |Melcher Tamara |Kletterverein mit Kletterrouten |Neudorfer Niklas |Gebäudeverwaltung (wo sind welche Geräte installiert zB Chromecasts) |Pavelescu Darius-Cristian |Musikdatenbank |Pelzeder Joachim |Personaleinteilung in Produktonsbetrieb mit Schichten (es wird durchgehend produziert) |Plakolb Marcel |Luftfahrtlinie (Wo fliegen die Flugzeuge, Linien) |Rathberger Jakob |Doodle |Remplbauer Markus |Modellagentur |Sugic Oliver |Schwimmverein |Tran Michael |Restaurant (Tischreservierung) |Tunc Johannes |Reisebüro |=== === Übung * Erstellen eines Datenmodell in plantuml (3-5 Entitäten) * Publishen zu gh-pages * Zusätzlich eine kurze Erklärung für die Anwendung * Termin: 11.11.2021 * Ordner im Root-Folder: asciidocs, backend, frontend * Erstellen eines Quarkus-Projekts mit einer Tabelle, persisitert in eine postgre-db und einem Endpoint === Erstellen einer aggregierten Abfrage ==== Schritt 1: Sql-Query [source,sql] ---- select substr(name,1,1), count(*) from person group by substr(name,1,1) order by 1; ---- ==== Schritt 2: Übertragen nach Java [source,java] ---- @Test void countLetters() { Query query = em.createQuery("select substring(p.name,1,1), count(p) from Person p group by substring(p.name,1,1)"); List list = query.getResultList(); for (Object[] elem : list) { logger.info(elem[0] + " - " + elem[1]); } assertThat(list.size()).isEqualTo(8); } ---- === Beziehungen zwischen Entitäten - Vererbung * http://edufs.edu.htl-leonding.ac.at/~t.stuetz/download/nvs/presentations.2021/06_JPA.pdf[Skriptum JPA ab Seite 44, window="_blank"] image::assoziative-Beziehung.png[] == 2021-11-16 === NamedQueries mit Parameter === Aggregated Queries .NamedQuery in Entity [source,java] ---- package at.htl.carrental.entity; import javax.persistence.*; @Entity @NamedQueries({ @NamedQuery( name = "Person.countByInital", query = "select substring(p.name,1, 1), count(p) from Person p group by substring(p.name,1, 1)" ) }) public class Person { // ... } ---- .Use NamedQuery in Repository [source,java] ---- @ApplicationScoped public class PersonRepository { @Inject EntityManager em; // ... public Map countByInitial() { Map result = new HashMap<>(); Query query = em .createNamedQuery("Person.countByInital"); List initials = query.getResultList(); for (Object[] initial : initials) { result.put( initial[0].toString().charAt(0), Integer.parseInt(initial[1].toString()) ); } return result; } } ---- .Test repository method [source,java] ---- @QuarkusTest class PersonTest { // ... @Test void countLetters() { Query query = em.createQuery("select substring(p.name,1,1), count(p) from Person p group by substring(p.name,1,1)"); List list = query.getResultList(); for (Object[] elem : list) { logger.info(elem[0] + " - " + elem[1]); } assertThat(list.size()).isEqualTo(8); } } ---- == 2021-11-29 Vorbereitung für Test-W * Cascadierende Assoziationen == 2021-12-07 Panache https://quarkus.io/guides/hibernate-orm-panache[Simplified Hibernate ORM with Panache] == 2021-12-13 Panache - Persistence Context image::persistence-context.png[] * Befindet sich ein Java-Objekt im Persistence Context, so hat es den Status "Managed" ** Ein Objekt kann den Zustand "managed" durch den Aufruf von persist() erhalten ** aber auch durch ein Holen des Objekts (Methode find()) aus der DB ** wichtig ist dabei, dass eine Transaktion aktiv ist *** Entweder Verwendung einer UserTransaction (mit tx.begin() und tx.commit()) *** oder Verwendung von @Transactional * Im Persistence Context kann man automatisch DB-Aktionen an abhängige Objekte weitergeben (zB cascading persist, ...) == 2021-12-14 === Datenzugriffs-Pattern ==== Repository-Pattern ==== Active-Record-Pattern === Queries in Panache == 2021-12-21 === Validation https://quarkus.io/guides/validation === Qute https://quarkus.io/guides/qute === Übung: Validierung und Qute im Microproject * Einbinden von Validation und Qute ins Mikroprojekt * zb Bei Validation: ** nicht alle (Entity-)Klassen müssen validiert werden. ** es sind allerdings die Konzepte aus dem Tutorial zu verwenden, zB *** vorgefertigte Validatoren *** Erstellung eines eigenen Validators * Es ist ein asciidoc-File zu erstellen (im Ordner asciidocs), in dem die Arbeiten dokumentiert werden. ** vergleichbar mit den Lecture (pro Datum ein Kapitel) ist auch in diesen adoc-File für jede Technologie (Übung) eine kurze Doku zu erstellen (Cheat Sheet) *** Warum benötige ich das? (Einsatzzweck) *** Ev. die Alternativen anführen *** Möglichkeiten der Anwendung (Code im Microproject kurz erklärt) ** diese Asciidocs sollen automatisch als gh-pages dargestellt werden *** https://github.com/htl-leonding-college/asciidoctor-docker-template/releases/tag/v1.1.4 *** https://github.com/htl-leonding-college/asciidoctor-convert-template image::tafelbild01-vmodell.jpeg[] image::tafelbild03-testen.jpeg[] image::tafelbild02-vmodell-scrum.jpeg[] image::tafelbild04-ucd.jpeg[] == 2021-12-23 === Übung: gRPC - Termin: 5. Jänner 2022 * Recherche: Was ist gRPC? (Einsatzzweck, welches Problem wird gelöst, Konzept) * Mutiny: https://quarkus.io/guides/getting-started-reactive * Verwendung in Quarkus -> Tutorials auf quarkus.io + image::grpc-tutorials.png[] * Einbauen ins Mikroprojekt und dokumentieren == Qute image::qute.png[] * Beispiel ** In der Klasse StudentResource sind die Qute-Template typisiert deklariert. ** Wird im Browser die jeweilige Route des Qute-Templates aufgerufen, liefert der Server die das gerenderte Template als html aus ** Der User kann nun zB ein Formular ausfüllen. ** Nach dem Klicken auf den Submit Button, werden die Inhalte der Formularfelder an den im Form-Attribut "action" angegeben REST-Endpoint übermittelt. ** Dieser REST-Endpoint gibt nun die neue Route jener Seite, die als nächstes angezeigt wird, an den Browser zurück == 2022-01-11 === Quarkus Security ==== Hausübung * Using Security with .properties File: https://quarkus.io/guides/security-properties * Using Security wit JDBC: https://quarkus.io/guides/security-jdbc ==== Besprochen Wir haben über Security mithilfe von Keycloak gesprochen: https://www.keycloak.org/downloads * Kleine mini quarkus Anwendung die geschützt werden (z.B.: nur rest teil) * User haben Rollen --> Rollen geben einen User gewisse Rechte, die er machen darf. == 2022-01-17 * assert: stelle sicher, Zusicherung image:projektarchitektur.jpeg[] .Bottom-Up (Basis-Ansatz) Einzelne Programmbestandteile werden definiert, eventuell sogar direkt geschrieben. Aus diesen Teilen werden dann größere Elemente des Programms zusammengesetzt, bis das vollständige System erstellt ist. .Top-Down (Vogelperspektive, Überbau-Ansatz) Grundlegender Architekturüberblick (Zuerst Landkarte => z.B.: Wo muss Technologie hin?) .REST-Service Daten zwischen Komponenten austauschen mit z.B.: Delete, Patch, Put, Get, Post .Metadata Daten über Daten. Z.B.: Datentyp, Autowert, ... .Daten Daten sind rohe, unorganisierte, zusammenhangslose Fakten. .Informationen * Informationen entstehen aus Daten * Daten werden verwendet zur Problemlösung, dann werden diese Daten zu Informationen * Wenn man Daten verarbeitet, organisiert, strukturiert oder in bestimmten Kontext stellt .Data Mining Mit mathematischen Methoden Zusammenhänge zwischen Daten ermitteln. Z.B.: Wenn man Bier kauft, kaufen viel auch Chips => daher sind meistens Bier und Chips in unmittelbarer Nähe von einander .Testen Nicht zu viele Tests, aber auch nicht zu wenige Tests. * assertj * myBatis * jdbc == 2022-02-03 === Rest-Client image::rest-client.png[] === Übung Mikroprojekt * Einen Zugriff auf einen REST-Service implementieren ** https://httpbin.org/ ** https://http.cat/ ** https://www.boredapi.com/ ** https://quotes.rest/ == 2022-02-08 === Unit--Testing ==== Test Struktur ===== Arrange-Act-Assert * AAA-Pattern ===== Given-When-Then == 2022-02-15 === Kotlin - Grundlagen * http://edufs.edu.htl-leonding.ac.at/~t.stuetz/download/android/01-kotlin-grundlagen/01_Introduction.pdf[01_Introduction.pdf^] * http://edufs.edu.htl-leonding.ac.at/~t.stuetz/download/android/01-kotlin-grundlagen/02_Functional_Programming.pdf[02_Functional_Programming.pdf^] //// * http://edufs.edu.htl-leonding.ac.at/~t.stuetz/download/android/01-kotlin-grundlagen/03_Object_Orientation.pdf[03_Object_Orientation.pdf^] * http://edufs.edu.htl-leonding.ac.at/~t.stuetz/download/android/01-kotlin-grundlagen/04_Android.pdf[Android^] //// == 2022-02-17 (Do.) SYP-Ersatzstunde === Einrichten der oravm == 2022-02-08 - Foliensätze Kotlin == 2022-03-10 Erstes Android Project === CoolDroid (siehe labs folder) * ist noch ohne jetpack compose mit xml-files == 2022-03-29