2020-08-04 Urlaub, Logo Review und Webservice Calls

Diese Woche ist Verena im Urlaub, trotzdem ging es weiter.
Unser Logo für die App nimmt weiter Gestalt an. Beim Review war Verena auch noch dabei. Bisher sind wir mit den Farben und dem Gesamteindruck aber noch nicht zufrieden und stehen weiterhin in Kontakt mit Gigblast, die wir auf Fiverr gefunden haben.
Ansonsten ging es diese Tage vorrangig um „Best Practices“ für die Bereitstellung und die Konsumierung von Webservices.

Peter
Als Backend für die Bereitstellung von Webservices nutzen wir Spring Boot. Unsere bisherigen Implementierungen waren aber sehr rudimentär. D.h. wir hatten Ressourcen wie eine Person, die man erstellen und hinzufügen, bestehende aktualisieren, löschen und auslesen konnte.
Zukünftig wird das Model aber deutlich komplexer sein. Es wird Beziehungen zwischen Ressourcen geben, es soll gefiltert, sortiert und gepagt werden.

Bisher haben wir bei einer Abfrage einer Ressource auch generell alle Attribute zurückgegeben. Obwohl ich zu Beginn der Meinung war, es macht nichts aus immer alles zurückzugeben, ist es im mobilen Sektor natürlich sinnvoll die Menge der zu übertragenen Daten so gering wie möglich zu halten. Außerdem ist es auch der Performance zuträglich.

Das Thema Einschränkung hat mich am meisten interessiert, deshalb habe ich damit begonnen zu schauen wie Daten, Attribute und Felder gefiltert werden können.  Beispielsweise sollte folgende Abfrage möglich sein:

http://localhost:8080/api/persons?fields=id,firstname

Mit diesem RESTCall werden alle Personen ausgelesen, aber von diesen Personen lediglich die Attribute id und firstname zurückgegeben.

Da es viele Endpunkte zum Auslesen von Ressourcen geben wird, wäre der Implementierungsaufwand für die Ausprogrammierung jedes Endpunkts recht hoch. Deshalb habe ich nach einem generischen Ansatz gesucht. Auch nach längerer Suche bin ich mit den vorgeschlagenen Lösungen aber nicht so recht zufrieden gewesen. Letztendlich hatte ich sogar überlegt es selbst und händisch zu implementieren. Dann bin ich aber über stackoverflow auf die Library Squiggly gestoßen. Mega cool. Lediglich nur 4 Votes für diese Hammer Lösung, die genau das kann, was wir brauchen. Dependency hinzufügen, eine Config-Klasse implementieren und nach 5 – 10 min Aufwand war es möglich für alle Ressourcen nach beliebigen Attributen zu filtern. Das Ausschließen von Attributen ist genauso möglich. Auch das Filtern von nested Attributen hat auf Anhieb funktioniert. Hat mich richtig aus den Socken gehauen. Denn generell funktioniert eine Lösung entweder erst einmal gar nicht oder macht nicht das was man braucht.
Hier ein paar Beispiele, die unterstützt werden

http://localhost:8080/api/persons?fields=id,firstnameAlle Personen beschaffen, id und firstname zurückgeben
http://localhost:8080/api/persons?fields=*Alle Personen mit allen Feldern zurückgeben (oder einfach „?field=*“ weglassen)
http://localhost:8080/api/persons?fields=-firstnameAlle Personen beschaffen das Attribut firstname vom Ergebnis ausschließen
http://localhost:8080/api/persons/1?fields=id,firstnamePerson zur id 1 beschaffen, id und firstname zurückgeben
http://localhost:8080/api/persons/1?fields=firstname,teams.namePerson zur id 1 beschaffen, firstname und das nested Attribut teams.name zurückgeben
http://localhost:8080/api/persons?fields=-teams.descriptionAlle Personen beschaffen und das nested Attribut teams.description ausschließen

Nächstes Thema war ein Best Practice für die Umsetzung der Webservices. Generell gibt es nun grob die folgenden Komponenten:

  • Endpunkte (Controller) – die Endpunkte selbst, die von außen aufgerufen werden können
  • Service Klassen – eine Art Use Cases, die für die Beschaffung, Filterung, Sortierung bestimmter Daten verantwortlich sind
  • DTOs – Data Transfer Objekte, die bestimmte Informationen bspw. unterschiedlichen Entitäten wrappen
  • Repositories – speziell für das Speichern, Auslesen von Daten aus bspw. einer Datenbank
  • Model – Entitäten, wie Personen, Teams etc.

Letztes Thema war das Konsumieren der Webservices aus einer App heraus – mit Hilfe von Retrofit. Hier hatten wir ein bestehendes Beispiel aus den letzten Wochen, das ebenfalls wenig komplex war.
Nach etwas rumspielen ist es nun aber auch möglich, nested Ressources mit auszulesen und Daten zu filtern. Ein Beispiel ist unser PersonDTOService. Über @Query ist es jetzt beispielsweise möglich die Filterkriterien zu übergeben, die im Ergebnis berücksichtigt werden. Zum Beispiel die Einschränkung des Ergebnisses auf bestimmte Attribute wie: firstname.

interface IPersonDTOService {

    @GET("persons")
    fun findAll(): Call<List<PersonDTO>>

    @GET("persons")
    fun findAll(@Query("fields") fields: String): Call<List<PersonDTO>>

    @GET("persons/{id}")
    fun findById(@Path("id") id: Long): Call<PersonDTO>

    @GET("persons/{id}")
    fun findById(@Path("id") id: Long, @Query("fields") fields: String): Call<PersonDTO>

    @POST("persons")
    fun addPerson(@Body personDTO: PersonDTO): Call<PersonDTO>
}

Last but not least habe ich begonnen die Verwendung von Retrofit etwas zu vereinfachen, da oft Coding doppelt geschrieben werden muss. Damit werde ich allerdings kommende Woche weitermachen.

Schreibe einen Kommentar