Write endpoints section

This commit is contained in:
Marcel Schwarz 2020-06-11 01:02:00 +02:00
parent 88bc4517fe
commit 41b53998de

View File

@ -122,6 +122,139 @@
Die "RecordOverviewProjection" reichert eine normale "Record" Ressource noch zusätzlich mit dem Username und den Accountnamen an. Dadurch muss nicht für jeden Record erneut einzeln der Accountname nachgeschlagen werden. Zudem wird noch ein, bei jeder Anfrage neu berechnetes, zusätzliches Feld angefügt. Die Dauer des Records in Minuten.
\section{Endpoints}
\subsection{HAL und Paging}
Die vier Hauptendpoints sind sicherlich die unserer Hautptressourcen: locations, accounts, records und users. Unten gibt es noch den nicht implementierten Endpoint für die Rollen ("roles") dieser liefert aber kaum Informationen. Der "profile" Endpoint wird erst im nächsten Kapitel erläutert. Um diesen Output zu bekommen muss der Nutzer authentifiziert sein. Dies geschieht wie oben schon erwähnt über den "/login" Endpoint. Da dieser aber keine Ausgaben außer dem Header mit dem Token liefert, wird er hier nicht weiter erläutert. Selbiges gilt auch für den "/sign-up" Endpoint. Alle Anfragen die ab jetzt ausgeführt werden geschehen immer mit vorheriger Authentifizierung.
\begin{lstlisting}[language=json,caption=Zugriff auf die Route "/" der API,label=code:main-route-api]
{
"_links": {
"locations": {
"href": "http://localhost:5000/locations{?page,size,sort}",
"templated": true
},
"accounts": {
"href": "http://localhost:5000/accounts{?page,size,sort,projection}",
"templated": true
},
"records": {
"href": "http://localhost:5000/records{?page,size,sort,projection}",
"templated": true
},
"users": {
"href": "http://localhost:5000/users{?page,size,sort,projection}",
"templated": true
},
"roles": {
"href": "http://localhost:5000/roles"
},
"profile": {
"href": "http://localhost:5000/profile"
}
}
}
\end{lstlisting}
\begin{lstlisting}[language=json,caption=Zugriff auf die Route "/locations" der API,label=code:locations-route-api]
{
"_embedded": {
"locations": [
{
"latitude": 1.0,
"longitude": 2.0,
"radius": 3,
"_links": {
"self": {
"href": "http://plesk.icaotix.de:5000/locations/1"
},
"locations": {
"href": "http://plesk.icaotix.de:5000/locations/1"
}
}
}
]
},
"_links": {
"self": {
"href": "http://plesk.icaotix.de:5000/locations{?page,size,sort}",
"templated": true
},
"profile": {
"href": "http://plesk.icaotix.de:5000/profile/locations"
}
},
"page": {
"size": 20,
"totalElements": 6,
"totalPages": 1,
"number": 0
}
}
\end{lstlisting}
Aufgrund der massiven Größe der Ausgaben der API werden die weiteren Ressourcen nur noch mit ihrem Link angegeben. Alle Ressourcen unterstützen zudem die CRUD Operationen auf einzelnen Ressourcen als auch auf der Hauptressource, deshalb werden sie aus Platzgründen ebenfalls übergangen.
\subsection*{Endpoints für Ressourcen}
\begin{itemize}
\item \verb|/locations{?page,size,sort,projection}|
\item \verb|/locations/<nr>{?projection}|
\item \verb|/roles{?page,size,sort,projection}|
\item \verb|/accounts{?page,size,sort,projection}|
\item \verb|/accounts/<nr>{?projection}|
\item \verb|/accounts/<nr>/user{?projection}|
\item \verb|/accounts/search/findByUsernameAndName{?username,account,projection}|
\item \verb|/accounts/search/findByUsername{?username,page,size,sort,projection}|
\item \verb|/users{?page,size,sort,projection}|
\item \verb|/users/<nr>{?projection}|
\item \verb|/users/<nr>/location{?projection}|
\item \verb|/users/<nr>/role{?projection}|
\item \verb|/users/search/byUsername{?username,projection}|
\item \verb|/records{?page,size,sort,projection}|
\item \verb|/records/<nr>{?projection}|
\item \verb|/records/<nr>/account{?projection}|
\item \verb|/records/search/allBetweenAndUser{?start,end,username,page,size,sort,projection}|
\item \verb|/records/search/openEntries{?page,size,sort,projection}|
\item \verb|/records/search/today{?page,size,sort,projection}|
\item \verb|/records/search/allForUser{?username,page,size,sort,projection}|
\item \verb|/records/search/allBetween{?start,end,page,size,sort,projection}|
\item \verb|/records/search/allFrom{?date,page,size,sort,projection}|
\item \verb|/records/search/allForUserAndAccount{?username,account,page,size,sort,projection}|
\end{itemize}
Wenn Ressourcen aktualisiert werden müssen, müssen die Daten immer im JSON Format vorliegen. Die Felder des JSON Objekts müssen mit denen der Ressource übereinstimmen. Es müssen aber nicht alle Felder Werte beinhalten. Soll eine neue Ressource erstellt werden, werden die Daten als POST abgesendet, bei einer Aktualisierung als PATCH. Links zwischen Ressourcen können über den Self Link der Ressource hergestellt werden. Weiter gibt es noch zwei komplett selbst gebaute Endpoints.
\subsection*{Der "/whoami" Endpoint}
Dieser Endpoint dient um nach dem Login schnell die Startseite der App oder der Webseite mit den Nutzerdaten zu befüllen. Es sind Daten wie der Vor- und Nachname, sowie der Username enthalten. Zusätzlich wird noch die gesetzte Location des Nutzers mitgegeben.
\subsection*{Der "/track" Endpoint}
Beim "/track" Endpoint handelt es sich um einen der wichtigsten Endpoints. Er erlaubt es ein Recording zu erstellen, ohne Angabe des Nutzers. Lediglich der Name des Timetrack Accounts auf den gebucht werden soll muss angegeben werden. Der Endpoint entscheidet auf Serverseite von welchem Nutzer die Anfrage ankam. Dazu wird der Nutzer aus dem JWT extrahiert und abhängig davon im Account des Nutzers geschaut ob schon ein Tracking läuft oder nicht. Sollte noch kein Tracking laufen, wird ein neuer Eintrag mit der aktuellen Zeit erstellt und zurückgeliefert. Das Enddatum ist zu diesem Zeitpunkt noch leer und auch die Duration zeigt "0" an. Sollte schon ein Tracking laufen, wird dieses mit der aktuellen Zeit als Endzeit beendet und ebenfalls zurückgeliefert. Sollte der Account nicht gefunden werden, oder ein anderer Fehler auftreten, wird ein entsprechender HTTP Statuscode zurückgeliefert.
\begin{lstlisting}[language=json,caption=Aufruf von "/track" ohne und mit laufendem Tracking,label=code:start-tracking-endpoint]
{
"duration": 0,
"username": "scma",
"account": "Demo",
"startdate": "2020-06-11T00:59:22",
"enddate": null,
"type": "PAID"
}
{
"duration": 129,
"username": "scma",
"account": "Demo",
"startdate": "2020-06-10T22:47:55",
"enddate": "2020-06-11T00:57:41",
"type": "PAID"
}
\end{lstlisting}
\subsection{HAL, Paging und Sorting}
Die Hypertext Application Language, kurz HAL, ist eine Spezifikation, mit der APIs automatisch erkundbar gemacht werden können. Sie bietet META-Elemente an einige davon werden auch bei uns benutzt.
\begin{itemize}
\item \textbf{"\_links"} zeigt weiterführende Links zu Ressourcen oder Informationen zum Paging an.
\item \textbf{"\_embedded"} enthält die Nutzdaten zur entsprechenden Ressource aber auch weitere Einbettungen zu Sub-Ressourcen.
\end{itemize}
Zusätzlich dazu nutzt Spring bei der Generation der Repositories auch teile der Hypermedia as the Engine of Application State, kurz HATEOAS, Spezifikation. Das Listing \ref{code:main-route-api} zeigt hierfür den zusätzlichen Endpoint "profile". Unter diesem sind viele Spezifikationen zu finden, wie alle anderen Routen auf bestimmte Daten reagieren und auch antworten.
Der "profile" Endpoint zeigt zusätzlich noch alle Projektionen an, die auf eine bestimmte Ressource angewendet werden kann. Der Name der Projektion wird dann durch den URL-Parameter "projection=" angehängt.
Zuletzt gilt es noch zu erwähnen, dass alle Ressourcen Paging und Sorting unterstützen. Paging ist besonders bei Web APIs wichtig, da die Geschwindigkeit sehr stark von der Menge der übertragenen Daten abhängt. Wenn eine Ressource immer alle Daten zurückliefern würde, würde dies bei mehreren hundert Einträgen sicher noch funktionieren. Aber sobald die Zahl der Einträge deutlich höher wird, muss abgeschnitten und aufgeteilt werden. Unsere Standard Seitengröße ist auf 20 Einträge gesetzt. Weiter enthält die Antwort des Servers durch die HAL Integration immer Links zur aktuellen, nächsten und vorherigen Seite als Link. Sorting wird ebenfalls unterstützt. Es kann nach jedem Feld im zurückgegebenen JSON Sortiert werden, auch die Richtung ist spezifizierbar.
\section{Probleme und Lösungen}
\section{Deployment}
Das Deployment des Backends findet immer gleichzeitig mit der Datenbank und dem Frontend statt. Die Daten bleiben dabei erhalten und werden, so fern nötig, von Spring automatisch migriert. Auch beim hinzufügen oder entfernen von Feldern aus Entitäten aktualisiert Spring die Datenbanktabellen entsprechend den neuen Feldern. Sollten Felder wegfallen werden diese einfach gelöscht, kommen neue hinzu wird entweder der Defaultwert gesetzt oder, wenn erlaubt, "Null".