IdbRestApiDoku.jsp Dokumentation der REST-Schnittstelle von IDB

Allgemeines

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:

Gibt es eine neue Version der Schnittstelle bekämen Sie vorab eine Datei idb.war. Anleitung zum Aktualisieren:

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:

Folgende Verfahren sind relativ neu hinzugekommen: Folgende Verfahren sind ganz neu hinzugekommen:

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.

Zu den property-Namen der Property-Value-Pärchen.

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:

Im Zweifelsfall können Sie aber auch mit uns Kontakt aufnehmen und uns wegen konkreten Anforderungen fragen. In den meisten Fällen würden wir Ihnen dann mit Beispiel-Code antworten, was meist mehr sagt als tausend Worte.

Client-Beispiele

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.

Milchkuh

Beispiel für die Nutzung von computemilchkuhchanges()

Milchkuh hat keine eigene changes-Liste für die verschiedenen Futterarten (Kraft-/Saft- und Grobfutter), da kein Futter in verschiedenen Listen vorkommt. Der Service findet das Futter selber in der richtigen Liste. Sie müssen aber bedenken, ob Sie den Anteil per Menge oder Prozent angeben müssen. Details dazu im Code.

Achtung: Die Liste der möglichen Futtermittel hat sich die letzten Wochen geändert, die IdbRestKonstantenMilchkuh ist aktuell.

Winterweizen

Beispiel für die Nutzung von computewinterweizenchanges()

Achtung, dieses Verfahren wurde erweitert um changesMaschinenarbeiten und changesDuenger. Damit lassen sich Maschinenarbeiten und direkte Düngergaben per Ids (aus den Konstanten) setzen. Dies gilt für alle Pflanzenbau-Verfahren.

Schweinemast

Beispiel für die Nutzung von computeschweinemastchanges()

Achtung: Aktuell ist es nicht möglich unterschiedliche Anteile beim Futter für die unterschiedliche Phasen anzugeben. Das wird sich in Kürze ändern, wenn wir mit allen Nutzern der Schweinemast-Schnittstelle kommuniziert haben, wann es für eine Änderung passen würde.

Kalbin

Beispiel für die Nutzung von computekalbinchanges()

Kalbin hat keine eigene changes-Liste für die verschiedenen Futterarten (Kraft-/Saft- und Grobfutter), da kein Futter in verschiedenen Listen vorkommt. Der Service findet das Futter selber in der richtigen Liste. Sie müssen aber bedenken, ob Sie den Anteil per Menge oder Prozent angeben müssen. Details dazu im Code. Das ist gleich wie bei Milchkuh.

Achtung: Die Liste der möglichen Futtermittel hat sich die letzten Wochen geändert, die IdbRestKonstantenKalbin ist aktuell.

Bullenmast

Beispiel für die Nutzung von computebullenmastchanges()

Bullenmast hat im Gegensatz zu Milchkuh und Kalbin zwei Listen speziell für Futter, changesAufzuchtFutter und changesMastFutter. Das ist notwendig, weil dort Futtermittel in beiden Listen vorkommen. Setzt man FutterId in der normalen changes-Liste gibt das einen RestError in der Antwort.

Ferkelerzeugung

Beispiel für die Nutzung von computeferkelerzeugungchanges()

Ferkelerzeugung hat eine Vielzahl von verschiedenen Listen für die verschiedenen Phasen und Fütterungsarten für Futter. Das ist so wie Schweinemast noch werden muss. Die Namen sind jeweils changesXXXFutterYYY und selbsterklärend. Der TestClient hat da auch gute Beispiele.

Grassilage

Beispiel für die Nutzung von computegrassilagechanges()

Der Test/Beispiel-Code von Grassilage ist noch etwas dürftig, allerdings ist die Komplexität des Verfahrens weniger im technischen der Schnittstelle als in der Komplexität des Verfahrens selber. Wie bei allen Futterbauverfahren gibt es eine Menge Konstellationen für verschiedene Zwecke. Diese muss man erst in der Webanwendung sehen, bevor man weiss welche Parameter man setzen will. Hier ist es am Besten diese dann auch explizit zu setzen, selbst wenn dies aktuell default sein sollte. Also z.B. für Futter für eigene Milchkühe explizit "Für mich selber" und "Futter MJNEL" setzen.

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.

Silomais

Beispiel für die Nutzung von computesilomaischanges()

Hier gilt aktuell das selbe, was auch bei der Grassilage steht.

Bodenheu

Beispiel für die Nutzung von computebodenheuchanges()

Hier gilt aktuell das selbe, was auch bei der Grassilage steht.

Weide

Beispiel für die Nutzung von computeweidechanges()

Hier gilt aktuell das selbe, was auch bei der Grassilage steht.

Wintergerste, Sommergerste und Körnermais

Beispiel für die Nutzung von computewintergerstechanges(), computesommergerstechanges() und computekoernermaischanges()

Diese drei Verfahren sind sich so ähnlich, dass Test-Code und Konstanten in einer Datei sind. Im Gegensatz zu tierischen Verfahren und Futterbau sind sie auch sehr einfach.

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.

FAQ

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).