Java Training Block 9 – Tag 3 Modern Web, HTML, Javascript, JAXRS, AJAX, POST, JSON

Ich nehme derzeit an einer Akademie zum Java Fullstack Software Engineer teil. In den kommenden Wochen möchte ich hier meine Mitschrift, so gut es geht, aufzeichnen und mitteilen. Hier ist das, was ich vom dritten Tag in Block 9 gelernt und behalten habe:

Ergänzungen zu gestern

Hier noch ein nützlicher Link zu Restful APIs: https://restfulapi.net/http-methods/#put

XHR Zusammenfassung

XHR - XML-HTTP-Request (AJAX)

  1. Globales XHR-Objekt erzeugen
    var xhr = new XMLHttpRequest(); // ab ECMA-5.1
  2. Init / Config des XHR-Objektes
    xhr.open("GET","https://swapi.dev/api/people/" + personidvalue ,true);
    xhr.setRequestHeader("Accept","application/json"); // Call-Back-Funktion erzeugen xhr.onreadystatechange = function () { console.log("xhr.onreadystatechange" + xhr.readyState); }; xhr.onloadstart = function () { console.log("xhr.onloadstart"); }; xhr.onload = function () { console.log("xhr.onload"); }; xhr.onloadend = function () { console.log("xhr.onloadend"); }; xhr.onprogress = function () { console.log("xhr.onprogress"); };
  3. Senden
    xhr.send(); // GET-Methode
    xhr.send(data); // POST-Methode

XMLHttpRequest.readyState:

0 UNSENT Client has been created. open() not called yet.
1 OPENED open() has been called.
2 HEADERS_RECEIVED send() has been called, and headers and status are available.
3 LOADING Downloading; responseText holds partial data.
4 DONE The operation is complete.

Die Call-Back-Funktionen (Onload, onloaded,…) sind sinnvoll um das Log übersichtlicher zu machen. Sie ersetzen im Prinzip unsere "myCallback()" Funktion:

JSON

JSON =Java Script Objekt Notation

Datentypen wie bei Javascript.

Integer und double = number (Datentyp von 42).
Geschweifte Klammern mit Key und Values sind Maps, assoizative Array oder Objekte mit Eigenschaften und Eigenschaftswertens.
Der Datentyp von Inhaber ist ein Objekt.

---------------------

Javascript

Array

Wir öffnen das Array-Beispiel Block9/day03/array/planeten.htm:

Map ist eine Listenfunktion (also nicht wie bei Java ein key-value Paar). Es führt für jedes Element der Liste eine Methode (toUpper) aus. Das Ergebnis ist eine neue Liste.

Wir können das auch als anonyme Funktion oder als Lamda-Funktion ausführen:

Weitere Beispiele von Ref-Funktionen, anonyme Funktionen und Lambda Ausdrücken:

For Each:

Reduce (ist sehr schnell, sinnvoll bei großen Daten):


Uebung KehrwertService

Wir starten in IntelliJ den Kehrwertservice und testen es mit curl -X GET http://localhost:8099/kehrwertservice/kehrwert/10

Wir kopieren unsere Starwars-html von gestern und passen diese an:

Wichtig ist, dass @CrossOrigin in der Applikation eingetragen ist:

Sollte das so sein, aber trotzdem eine "CrossOrigin" Fehlermeldung auftreten, kann es sein, dass die URL im Client nicht richtig eingetragen ist.

Bei der Erstellung der Springboot Servers wurde automatisch eine statische html-Seite miterstellt:

Diese index.html-Seite tauschen wir aus mit dem Inhalt von uns und können jetzt sogar das CrossOrigin weglassen:

Hier das funktionierende HTML-File:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Hello Starwars person</title>
&lt;script type="text/javascript">
    // 1. XHR erzeugen
    let xhr = new XMLHttpRequest(); //ab ECMA--5

function makeCall(){
    let zahlvalue = parseFloat(document.getElementById("zahlid").value);
    //2. Init / Config des XHR Objektes
    xhr.open("GET","http://localhost:8099/kehrwertservice/kehrwert/"+zahlvalue, true)
   // xhr.setRequestHeader("Accept","application/json");

    //Call-Back-Funktion einbinden
   // xhr.onreadystatechange = mycallback;
    xhr.onloadstart =  () => {
        console.log("xhr.onloadstart");
        document.getElementById("butCalc").disabled=true;
        document.getElementById("zahlid").disabled=true;

};

        xhr.onloadend = () => {
             console.log("xhr.onloadend");
             document.getElementById("butCalc").disabled=false;
            document.getElementById("zahlid").disabled=false;
         };

         let msg = `
                &lt;span style="color: red">
                   Error: Server-Timeout
                 &lt;/span>
            `;

         xhr.ontimeout = () => {
            console.log("xhr.timeout");
            document.getElementById("butCalc").disabled=false;
            document.getElementById("zahlid").disabled=false;
            document.getElementById("outid").innerHTML=msg;
         }

         xhr.onload = () => {
             console.log("xhr.onload");
             console.log("xhr.readystate: "+xhr.readystate);
             let zahlvalue = parseFloat(document.getElementById("zahlid").value);
            let kw = xhr.responseText;
            let msg = "&lt;span style='color: blue'>"
            msg = msg + "Zahl: " +  zahlvalue;
            msg = msg + "Kehrwert: " +  kw;
            msg = msg + "&lt;/span>";
            document.getElementById("outid").innerHTML=msg;
             };
        xhr.onprogress = () => { console.log("xhr.onprogress");
    console.log("Rolling,....")};

        xhr.onerror = () => {
            console.log("xhr.timeout");
            document.getElementById("butCalc").disabled=false;
            document.getElementById("zahlid").disabled=false;
            let msg = "&lt;span style='color: red'> Error: Any Error has occured!";
            document.getElementById("outid").innerHTML=msg;
        }

    //3. Senden
    xhr.send();  // bei GET; Bei POST: xhr.send(data); -> data in den RequestBody
}
&lt;/script>

</head>
<body>
<header>
<h1> Kehrwert berechnen </h1>
<hr/>
</header>
<section>
<div>
<form>
<label for='personid' > ID <br/>
<input id="zahlid" name='zahl' type='number' value="" size='20' required placeholder="Bitte Zahl eingeben"/><br/>
</label>
<button id ="butCalc" type='button' onclick='makeCall();'>Calculate</button>
</form>
</div>
<div id="outid"></div>
</section>
</body>
</html>


Klassendefinitionen in JS

In Javascript ist eine Funktion das Gleiche wie ein assoziatives Array(map) wie ein Objekt.

Hier ein Oldschool-Beispiel:

Klassendefinitionen Javascript (ES5 und ES6) und TypeScript (von Microsoft):


JSON - POST

JSON-Object: Serialisierung / Deserialisierung bzw. Marshalling / Unmarshalling

Methoden

let jsonstream = JSON.stringify(BuchObjekt);              //Marshalling
let book = JSON.parse(jsonstream);                           //Unmarshalling
let jsonstream = JSON.stringify(objBuch);              //Marshalling
document.writeln("objBuch : " +objBuch);
document.writeln("jsonstream : " +jsonstream);
let book = JSON.parse(jsonstream);                       //Unmarshalling
document.writeln("Book Object : " +book);
document.writeln("Book Titel : " +book.titel);

JSON-Object: Kontext AJAX

Senden:
xhr.open("POST",URL,true);

xhr.send(jsonstream);

Empfangen:
jsonstream = xhr.responseText;

curl -v -X POST http://localhost:8099/kreisrechner/kreisobj -d "{\"radius\":\"4\"}" -H "Content-Type: application/json"

Uebung: Kreisrechner-Client:

AJAX-Zugriff auf Kreisrechner-Server:

curl -v -X GET http://localhost:8080/kreisrechner/flaeche/10
curl -v -X GET http://localhost:8080/kreisrechner/umfang/10  
curl -v -X POST http://localhost:8080/kreisrechner/kreisobj -d "{\"radius\":\"4\"}" -H "Content-Type: application/json"

Der Client soll:
a. Fläche GET PathVariable Radius -> Double
b. Umfang GET PathVariable Radius -> Double
c. Fläche + Umfang POST RequestBody xhr.send(kreisobjekt) {\"radius\":\"4\"}
-> Kreisobjekt {"radius":4.0,"flaeche":50.26548245743669,"umfang":25.132741228718345}

Eingabe für den Radius:
3 Buttons:
1. Löst Aufgabe a.
2. Löst Aufgabe b.
3. Löst Aufgabe c.
Ausgabebereich:
Radius + Fläche
Radius + Umfang
Radius + Fläche + Umfang
Kreis-Klasse: separate Datei
Hilfe: Kreis-Klasse
Class Kreis {
This.radius
This.flaeche
This.umfang
}

Funktionierendes File Kreisrechner-client.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Kreisrechner CLient</title>
    <script type="text/javascript" src="./Kreiswert-utilclass.js"></script>
    <script type="text/javascript">
        // 1. XHR erzeugen
        let xhr = new XMLHttpRequest(); //ab ECMA--5
        function makeCallFlaeche() {
            let radiusvalue = parseFloat(document.getElementById("radiusid").value);
            //2. Init / Config des XHR Objektes
            xhr.open("GET", "http://localhost:8099/kreisrechner/flaeche/" + radiusvalue, true)
            // xhr.setRequestHeader("Accept","application/json");
            //Call-Back-Funktion einbinden
            // xhr.onreadystatechange = mycallback;
            xhr.onloadstart = () => {
                console.log("xhr.onloadstart");
                document.getElementById("butFlaeche").disabled = true;
                document.getElementById("radiusid").disabled = true;
            };
            xhr.onloadend = () => {
                console.log("xhr.onloadend");
                document.getElementById("butFlaeche").disabled = false;
                document.getElementById("radiusid").disabled = false;
            };
            let msg = `
                    <span style="color: red"> 
                       Error: Server-Timeout
                     </span>
                `;
            xhr.ontimeout = () => {
                console.log("xhr.timeout");
                document.getElementById("butFlaeche").disabled = false;
                document.getElementById("radiusid").disabled = false;
                document.getElementById("outid").innerHTML = msg;
            }
            xhr.onload = () => {
                console.log("xhr.onload");
                console.log("xhr.readystate: " + xhr.readystate);
                let radiusvalue = parseFloat(document.getElementById("radiusid").value);
                let flaeche = xhr.responseText;
                let msg = "<span style='color: blue'>"
                msg = msg + "radius: " + radiusvalue;
                msg = msg + "Fläche: " + flaeche;
                msg = msg + "</span>";
                document.getElementById("outid").innerHTML = msg;
            };
            xhr.onprogress = () => {
                console.log("xhr.onprogress");
                console.log("Rolling,....")
            };
            xhr.onerror = () => {
                console.log("xhr.timeout");
                document.getElementById("butFlaeche").disabled = false;
                document.getElementById("radiusid").disabled = false;
                let msg = "<span style='color: red'> Error: Any Error has occured!";
                document.getElementById("outid").innerHTML = msg;
            }
            //3. Senden
            xhr.send();  // bei GET; Bei POST: xhr.send(data); -> data in den RequestBody
        }
    function makeCallUmfang() {
        let radiusvalue = parseFloat(document.getElementById("radiusid").value);
        //2. Init / Config des XHR Objektes
        xhr.open("GET", "http://localhost:8099/kreisrechner/umfang/" + radiusvalue, true)
        // xhr.setRequestHeader("Accept","application/json");
        //Call-Back-Funktion einbinden
        // xhr.onreadystatechange = mycallback;
        xhr.onloadstart = () => {
            console.log("xhr.onloadstart");
            document.getElementById("butUmfang").disabled = true;
            document.getElementById("radiusid").disabled = true;
        };
        xhr.onloadend = () => {
            console.log("xhr.onloadend");
            document.getElementById("butUmfang").disabled = false;
            document.getElementById("radiusid").disabled = false;
        };
        let msg = `
                &lt;span style="color: red"> 
                   Error: Server-Timeout
                 &lt;/span>
            `;
        xhr.ontimeout = () => {
            console.log("xhr.timeout");
            document.getElementById("butUmfang").disabled = false;
            document.getElementById("radiusid").disabled = false;
            document.getElementById("outid").innerHTML = msg;
        }
        xhr.onload = () => {
            console.log("xhr.onload");
            console.log("xhr.readystate: " + xhr.readystate);
            let radiusvalue = parseFloat(document.getElementById("radiusid").value);
            let umfang = xhr.responseText;
            let msg = "&lt;span style='color: blue'>"
            msg = msg + "radius: " + radiusvalue;
            msg = msg + "Umfang: " + umfang;
            msg = msg + "&lt;/span>";
            document.getElementById("outid").innerHTML = msg;
        };
        xhr.onprogress = () => {
            console.log("xhr.onprogress");
            console.log("Rolling,....")
        };
        xhr.onerror = () => {
            console.log("xhr.timeout");
            document.getElementById("butUmfang").disabled = false;
            document.getElementById("radiusid").disabled = false;
            let msg = "&lt;span style='color: red'> Error: Any Error has occured!";
            document.getElementById("outid").innerHTML = msg;
        }
        //3. Senden
        xhr.send();  // bei GET; Bei POST: xhr.send(data); -> data in den RequestBody
    }


    function makeKreisObjekt() {
        let radiusvalue = parseFloat(document.getElementById("radiusid").value);
        let kreisclass = new KreisUtilclass();
        kreisclass.radius = parseFloat(document.getElementById("radiusid").value);
        //2. Init / Config des XHR Objektes
        let jsonstream = JSON.stringify(kreisclass);
        xhr.open("POST", "http://localhost:8099/kreisrechner/kreisobj", true);
        // xhr.setRequestHeader("Accept","application/json");
        xhr.setRequestHeader("Content-Type", "application/json");
        //Call-Back-Funktion einbinden
        // xhr.onreadystatechange = mycallback;
        xhr.onloadstart = () => {
            console.log("xhr.onloadstart");
            document.getElementById("butKreisObjekt").disabled = true;
            document.getElementById("radiusid").disabled = true;
        };
        xhr.onloadend = () => {
            console.log("xhr.onloadend");
            document.getElementById("butKreisObjekt").disabled = false;
            document.getElementById("radiusid").disabled = false;
        };
        let msg = `
                &lt;span style="color: red"> 
                   Error: Server-Timeout
                 &lt;/span>
            `;
        xhr.ontimeout = () => {
            console.log("xhr.timeout");
            document.getElementById("butKreisObjekt").disabled = false;
            document.getElementById("radiusid").disabled = false;
            document.getElementById("outid").innerHTML = msg;
        }
        xhr.onload = () => {
            console.log("xhr.onload");
            console.log("xhr.readystate: " + xhr.readystate);

            if (xhr.status === 200) {
                let jsonstream = xhr.responseText;
                let kreis = JSON.parse(jsonstream);
                let radiusvalue = kreis.radius;
                let flaechenvalue = kreis.flaeche;
                let umfangvalue = kreis.umfang;
                let msg = "&lt;span style='color: blue'>"
                msg = msg + "radius: " + radiusvalue;
                msg = msg + "Umfang: " + umfangvalue;
                msg = msg + "Fläche: " + flaechenvalue;
                msg = msg + "&lt;/span>";
                document.getElementById("outid").innerHTML = msg;
            }
            else {
                document.getElementById("outid").innerHTML = xhr.responseText;
            }

        };
        xhr.onprogress = () => {
            console.log("xhr.onprogress");
            console.log("Rolling,....")
        };

        xhr.onerror = () => {
            console.log("xhr.timeout");
            document.getElementById("butKreisObjekt").disabled = false;
            document.getElementById("radiusid").disabled = false;
            let msg = "&lt;span style='color: red'> Error: Any Error has occured!";
            document.getElementById("outid").innerHTML = msg;
        }
        //3. Senden
        xhr.send(jsonstream);  // bei GET; Bei POST: xhr.send(data); -> data in den RequestBody
    }
&lt;/script>

</head>
<body>
<header>
<h1> Kreis berechen </h1>
<hr />
</header>
<section>
<div>
<form>
<label for='personid'> ID <br />
<input id="radiusid" name='radius' type='number' value="" size='20' required
placeholder="Bitte radius eingeben" /><br />
</label>
<button id="butFlaeche" type='button' onclick='makeCallFlaeche();'>Aufgabe a (Fläche)</button>
<button id="butUmfang" type='button' onclick='makeCallUmfang();'>Aufgabe b (Umfang)</button>
<button id="butKreisObjekt" type='button' onclick='makeKreisObjekt();'>Aufgabe c (Kreisobjekt)</button>
</form>
</div>
<div id="outid"></div>

&lt;/section>

</body>
</html>

Kreiswert-utilclass.js:

class KreisUtilclass {
    constructor(radius, flaeche, umfang) {
        this.radius = radius;
        this.flaeche = flaeche;
        this.umfang = umfang;
    }
}

Disclaimer

Alles was ich mitschrieb und verstanden habe ist ohne Gewähr. Die Bilder stammen teilweise aus dem Internet und wir haben keine Urheberansprüche darauf.

Besten Dank an unseren sehr empfehlenswerten

Trainer: Hans-Joachim Blanke blanke@4point.de

In den nächsten Tagen und Wochen geht’s weiter, so: stay tuned!

Gruß, Achim Mertens

H2
H3
H4
3 columns
2 columns
1 column
Join the conversation now
Logo
Center