IdbRestApiDoku.jsp
Zu den Verfahren aus dem Internet Deckungsbeitrag, die bereits mit der LfL Klima-Check Erweiterung versehen sind, gibt es jeweils je Verfahren eine entsprechende REST-Schnittstelle. Technisch ist dies durch JSON über REST implementiert.
Basis-URL ist https://www.stmelf.bayern.de/idb/rest/
Die maschinenlesbare Schnittstellenbeschreibung ist durch eine OpenApi-Spezifikation implementiert. Dabei gibt es eine OpenApi JSON und eine OpenApi YAML Version. Es dürfte für so gut wie jede Plattform Codegeneratoren geben, die aus der Spezifikation einen Client erzeugen. Auch um zukünftige Änderungen leichter aktualisieren zu können empfehlen wir, dass Sie dies nutzen.
Als Beispiel für Java sieht das so aus, dass man sich den Code-Generator openapi.jar (von hier) holt. Ich wollte als REST-Bibliothek jersey, also sah der Aufruf so aus, die ganzen package-Namen sind natürlich wie man will:
java -jar openapi.jar generate --api-package de.bayern.lfl.idb.rest.client.api --model-package de.bayern.lfl.idb.rest.client.model --invoker-package de.bayern.lfl.idb.rest.client.invoker --group-id de.bayern.lfl.idb.rest -g java --library jersey2 -i https://www.stmelf.bayern.de/idb/rest/openapi.json -o generated
Wenn Sie eine andere Umgebung nutzen (was bei der Vielzahl wahrscheinlich ist) wird wahrscheinlich trotzdem das openapi.jar-Java-Tool ihr Einstieg sein, weil dieser Clients für alle möglichen Umgebungen erzeugen kann.
Zusätzlich zu den verfahrensspezifischen Schnittstellen gibt es die Operation getMinVersion, die einen Versionscode (als YYYYMMDD-Datum) zurückliefert. Das ist nicht die aktuelle Version der API, sondern ändert sich dann, wenn die API so verändert wurde, dass evtl. Clients zu funktionieren aufhören könnten und Anpassung notwendig ist. Das sollte so selten wie möglich bis nie passieren. Sie müssen beim Implementieren nur schauen, auf welche MinimalVersion Sie aktuell abzielen (also das getMinVersion einmal aufrufen). Die Zahl verdrahten Sie dann am Besten auch in Ihren Clients oder irgendwelchen Watchern oder sowas. Sollte sich bei uns diese Version dann mal ändern wär das ein Anlass bei uns nachzufragen, ob und was sich geändert hat.
Es gibt noch ein paar Test-Operationen, die dazu dienen können, ein Problem einzugrenzen, wenn es technische Schwierigkeiten in der grundlegenden Kommunikation geben würde.
Sie sagen jetzt natürlich: "Wär schön, wenn wir das vorher schon wüssten". Und das würden wir auch anstreben. Ein kleines Problem ist, dass wir aus den Vorgaben unserer Sicherheit (BSI) keine Test- oder Vorabversionen im Internet publizieren dürfen. Wir haben eine Laufzeitumgebung für unsere Webanwendung inkl. Schnittstelle, die ohne Installation für Windows-PCs leicht zum Laufen zu bringen ist. Kurzanleitung dazu wäre:
Die Nutzung der idb.war ist nur für Entwicklungszwecke gestattet, Sie dürfen Sie nicht selber im Internet hosten.
Für jedes in der Schnittstelle implementierte Verfahren gibt es eine Operation. Diese sind:
Zum Verständnis der Schnittstelle zu einem Verfahren ist es notwendig sich zuerst mit dem gewünschten Verfahren in der Webanwendung vertraut zu machen.
Die REST-Schnittstelle basiert auf dem selben Service-Layer, den auch die Webanwendung verwendet. Da man aber nicht alle Eingabedaten schicken will (lahm und zu viele Details) ist das Konzept der Schnittstelle, dass man nur die Werte schickt, die man von den Defaults der Verfahren ändern will.
Daher ist der Kern der Eingabeparameter eine kleine Liste vom Typ PropertyValuePair, welcher einen String als property und eine Zahl als Wert für diese property hat. Welche properties es gibt kommt später bzw. sollte man sich dazu hauptsächlich den Beispiel Rest-Client Code anschauen, da sind die wichtigsten schon abzulesen, ohne dass man sich zu viel anschauen muss.
Es gibt nur eine komplizierte Besonderheit zu beachten. In der Webanwendung kann ein Mensch ja nur einen Wert zu einer Zeit ändern. D.h. nach einer Eingabe ist klar, welcher Wert geändert wurde und die Anwendung reagiert auf diese Änderung bevor die nächste Eingabe kommt. In der Schnittstelle kommt ja alles auf einmal und JSON garantiert ja keine Reihenfolge. Es gibt je Verfahren ein paar properties/Werte/Angaben, die nicht nur Auswirkungen auf sich selber und die Berechnung haben, sondern in Abhängigkeit von ihnen viele anderen Eingabefelder auf neue Defaults setzen.
Diese speziellen properties werden nicht in den changes per Property-Value Pärchen angesprochen, sondern existieren als explizite Parameter in den Eingabestrukturen der verfahrensspezifischen Parameter. Setzt man sie dort heisst das, dass man ausdrücklich den Wert und alle evtl. dann mit neuen defaults zu besetzenden Werte setzen will, bevor man die eigentlichen numerischen eigenen Werte setzen will. Klingt komplizierter als es in der Praxis ist. Meine Empfehlung an Sie ist auch, das Thema mit einem Stirnrunzeln und einem Nicken zu akzeptieren und sich nur folgendes zu merken: "Gibt es für das, was ich setzen will, einen expliziten Parameter nimm den, ansonsten setze es über Property-Value-Pärchen". Und eigentlich ist auch der universelle "Ich schau es mir im Beispiel-Code an, dann werde ich es schon verstehen"-Ansatz noch besser.
Die Pflege einer menschenlesbaren Schnittstellenbeschreibung für alle Werte ist uns leider vom Aufwand her nicht möglich und auch nicht sinnvoll. Jedoch sind alle für die Schnittstelle notwendigen Informationen trotzdem leicht zugänglich.
Die name-tags der Controls der Webanwendung entsprechen nämlich den property/value Pärchen der REST-Schnittstelle. Beispiel:
<td class="grundlegendTableCell" style="display:none;"> <input type="text" name="rech.param.kaelberJeKuhUndJahr" maxlength="8" size="5" value="1.12" onchange="cleanEingabe(this),milchKennwerteModule.chgHandlerKaelberProJahr()" id="milchKennwertekaelberJeKuhUndJahr"> </td>
Als Dokumentation und Einstieg gibt es zu jedem Verfahren Test-Code. Dieser ist in Java geschrieben, aber sollte von jedem Programmierer gelesen werden können. Der Code nutzt diese kleine Klasse mit Helper-Funktionen um selber leserlicher zu sein:
Jedes Verfahren hat dabei zwei Java-Klassen: Den Test-Code und eine Sammlung von Konstanten für das Verfahren. Zweiteres sollten/wollen Sie ziemlich direkt in Ihre Umgebung übertragen, ersteres dient eher als Doku. Bitte beachten Sie, dass neue Verfahren evtl. noch wenig Testcode für Sonderfälle haben, weil wir diese jeweils erweitern, wenn Kunden mit bestimmten Fragen gekommen sind.
Alle Operationen auf Verfahren haben im Rückgabeparamter paramIn ein property restErrors. Ist diese nach einem Aufruf nicht leer ist ein Fehler aufgetreten und das Ergebnis kann nicht verwendet werden. Die Fehler sind menschenlesbar, aber nicht für End-Benutzer gedacht. Die Fehler dort sind normalerweise nicht REST-technischer Natur, sondern Fehler wie "Wenn Sie in einer Futtermittel-Änderungsliste was übergeben, müssen Sie auch spezifizieren, welches Futtermittel Sie per FutMitId ändern wollen.". Also Sachen, die eigentlich in der Entwicklung schon alle gefixed würden, aber evtl. auch mal einen ungültigen Parameter. Die möglichen Fehler, die man machen kann, sind so unendlich, dass bei weitem nicht alles abgefangen ist. Wenn z.B. für ein Feld Code 1-5 erlaubt ist und der Client 6 schickt, dann ist die Chance gut, dass es ein kaputtes Ergebnis gibt und keine schöne Fehlermeldung. Daher ist die Nutzung der IdbRestKonstantenXXX fast notwendig.
Beispiel für die Nutzung von computemilchkuhchanges()
Achtung: Die Liste der möglichen Futtermittel hat sich die letzten Wochen geändert, die IdbRestKonstantenMilchkuh ist aktuell.
Beispiel für die Nutzung von computewinterweizenchanges()
Beispiel für die Nutzung von computeschweinemastchanges()
Beispiel für die Nutzung von computekalbinchanges()
Achtung: Die Liste der möglichen Futtermittel hat sich die letzten Wochen geändert, die IdbRestKonstantenKalbin ist aktuell.
Beispiel für die Nutzung von computebullenmastchanges()
Beispiel für die Nutzung von computeferkelerzeugungchanges()
Beispiel für die Nutzung von computegrassilagechanges()
Bei Unklarheiten bitte schnell Rückmeldung, das Verfahren ist neu und noch von niemand in der Praxis benutzt. Es ist zwar gut getestet, aber komplex genug.
Beispiel für die Nutzung von computesilomaischanges()
Beispiel für die Nutzung von computebodenheuchanges()
Beispiel für die Nutzung von computeweidechanges()
Beispiel für die Nutzung von computewintergerstechanges(), computesommergerstechanges() und computekoernermaischanges()
Ein wichtiger Hinweis zum Parameter Betrachtungszeitraum, den jedes Verfahren als direktes property hat, weil sich an Hand von diesem sehr viele auch direkt ansprechbare Parameter auf neue Vorbelegungen stellen: Die möglichen Betrachtungszeiträume ändern sich relativ häufig (ein bis zweimal im Jahr) und auch nicht bei allen Verfahren gleichzeitig. Wenn Sie von Ihrem Client explizit Betrachtungszeiträume auswählen lassen wollen, müssen Sie die Auswahl recht häufig aktualisieren. Ich würde das an Ihrer Stelle nicht leichtfertig machen und es lieber immer beim Standard-Betrachtungszeitraum lassen.
Der Code ist explizit als Dokumentation gedacht. Von vom Code losgelöster Prosa halte ich nichts.
F: Wie häufig ändern sich die Vorbelegungen?
A: Mindestens wenn sich die Betrachtungszeiträume ändern bei Pflanzenbauverfahren,
eigentlich wöchentlich bei den tierischen Verfahren. Dabei sind die ökonomischen
Parameter sehr viel häufiger von Änderungen betroffen (Preise ändern sich
bei tierischen Produkten wöchentlich) als die THG-Parameter.
F: Ist es möglich einen früheren Aufruf mit den alten Default-Werten bzw. auch
mit den alten Berechnungsverfahren (sollte sich das geändert haben) zu wiederholen?
A: Wir behalten selbst Versionen der Anwendung auf Archiv um jeden Stand, der einmal produktiv war,
jederzeit reproduzieren zu können. Das ist aber mit genug Aufwand verbunden,
dass wir das nur für besondere Fälle (Gerichtsverhandlungen für Hagelschäden
oder sowas) zur Verfügung stellen können. Im Zweifelsfall fragen Sie bei uns
an, wenn Sie einen Anwendungsfall für das haben.
F: Der Aufruf ist ewas langsam (3 Sekunden), wir nutzen ihn interaktiv und
da ist das fast ein bisschen lästig...
A: Die Aufruf-Zeit bleibt praktisch komplett im Einpacken der Antwort ins JSON
und vor allem im Rückübermitteln der Antwort übers Netz hängen. Das Antwort
Objekt mit allem was ein Verfahren an Zahlen hat ist EXTREM dick.
Das Zeitverhalten liesse sich enorm verbessern, wenn
wir für spezielle Client-Wünsche spezielle Operationen für die gewünschten
Verfahren mit Antwort-Objekten schaffen würden, die nur genau das beinhalten,
was der Client eigentlich will. Das macht die Schnittstelle für uns aber immer
wartungsintensiver, so dass wir das nicht schon a priori anbieten. Für spezielle Kooperationen
wird so etwas bestimmt geschaffen. Denkbar ist auch, dass sich mehrere Kunden absprechen
und uns eine "Obermenge der speziellen Wünsche" nennen.
F: Gibt es Gründe keine schlanke Variante der Schnittstelle (siehe vorige Frage) zu wollen?
A: Das grosse Antwort-Objekt enthält viele Zwischenergebnisse und vor allem auch
alle verwendeten Default-Eingabe-Parameter der Berechnung. Wenn Sie die Berechnung
für eine offzielle Berechnung verwenden wollen (so was wie "Düngeverordnung
für CO2", wenn es sowas mal gibt oder gäbe), dann sollten Sie das ganze
Antwort-Objekt als Beweis für das verwendete Ergebnis speichern. Da wär es
evtl. gut, wenn Sie auf das rohe JSON aus Ihrem Client zugreifen können, weil
das als BLOB gespeichert diese Anforderung am billigsten erfüllen würde.
F: Ich rufe die Schnittstelle auf, erhalte aber leicht andere Zahlen als in
der Webanwendung?
A: Die serverseitige Implementierung der Berechnung in Java nutzt anderen
Code als die client- (browser-)seitige Berechnung in JavaScript.
Auf dem Server können wir Vererbung für die Unterschiede/Gemeinsamkeiten
der Berechnung der Verfahren nutzen, während wir auf Client-Seite viel mehr
darauf achten müssen die Oberfläche und deren Unterschiede/Gemeinsamkeiten
wartbar zu halten. Leichte Unterschiede treten jetzt überall da auf, wo wir
unterschiedlich runden bzw. mit unterschiedlich gerundeten Zwischenergebnissen
weiterrechnen. Da es keine Vorgabe gibt, wie und wann zu runden ist, ist weder
das eine Ergebnis noch das andere falsch oder richtiger. Wir achten zwar schon
darauf, dass, wenn uns so ein Ort auffällt, wir das harmonisieren. Dies ist aber recht
aufwändig zu testen und nicht besonderes wichtig, so dass uns da immer mal ein
Unterschied durch die Finger rutscht. Um zu schauen, ob Sie vielleicht doch
nicht genau das Richtige schicken, vergleichen Sie Ihre Ergebnisse der
Schnittstelle nicht mit der Webanwendung selber, sondern mit dem daraus
erzeugten PDF. Das PDF wird auf dem Server erzeugt und hätte die selben
Ergebnisse wie die Schnittstelle. Wenn nicht, wäre eine Nachfrage bei uns immer
gut, weil es sich dann evtl. um einen Bug in der Anwendung handelt.
F: Schweinemast: Haltungsform und Wirtschaftsdünger, gibt es dazu was zu sagen?
A: Ja, tatsächlich. Ich kopiere hier den Text einer E-Mail rein, bei der mir aufgefallen ist, dass es dazu was dokumentationswürdiges gibt:
Wobei das in dem Fall nicht ganz einfach ist, weil manche Wirtschaftsdünger-Varianten je nach Haltungsform ausgeblendet sind.
Bei den Haltungsformen 1+2 Stallhaltung (im Verfahren bei den "Kennwerten des Produktionsverfahren" bei "Haltungsform") ist bei Wirtschaftsdünger "Gülle" (Kennzahl für Schnittstelle 1) und "Festmist/Jauche" (Kennzahl 3) auswählbar. Bei Haltungsform "4 Premium" ist nur die 3 - Festmist/Jauche erlaubt. Von der Schnittstelle hier würde hier 1-Gülle auch rechnen, aber das wäre wohl bei "4 Premium" einfach nicht erlaubt, weil es dann wohl nicht mehr als Premium zählen darf. Bei Haltungsform "3 Aussenklima" wird es wild. Bei dieser Haltungsform ist gar nichts mehr auswählbar und die Wirtschaftsdüngerberechnung verzweigt in eine eigene Mischberechnung für diese Haltungsform. Für Haltungsform "3 Aussenklima" darf keine Wirtschaftsdünger-Variante gesetzt sein, das muss also null bleibenn. Eine Oberfläche, die die Auswahl der Haltungsformen erlaubt, muss sich da das Verhalten da am Besten von der IDB-Webanwendung abschauen.
Das Verhalten der Anwendung bei Änderung der Haltungsformen bewirkt im Allgemeinen einige Detail-Änderungen, die sich aber nur auf den ökonomischen Teil auswirken (bestimmte Preisabschläge/-zuschläge, die nur bei 3-Aussenklima und 4-Premium sichtbar und effektiv werden).