Wann sollte ich RequestFactory vs GWT-RPC verwenden?

87

Ich versuche herauszufinden, ob ich meine gwt-rpc-Aufrufe auf die neuen GWT2.1 RequestFactory-Kaliber migrieren soll.

In der Google-Dokumentation wird vage erwähnt, dass RequestFactory eine bessere Client-Server-Kommunikationsmethode für "datenorientierte Dienste" ist.

Was ich aus der Dokumentation entnehmen kann, ist, dass es eine neue Proxy-Klasse gibt, die die Kommunikation vereinfacht (Sie geben nicht die eigentliche Entität hin und her, sondern nur den Proxy, sodass sie leichter und einfacher zu verwalten ist).

Ist das der springende Punkt oder fehlt mir noch etwas im großen Ganzen?

Daghan ---
quelle
8
yay, diese frage ist vom offiziellen gwt devguide verlinkt !
Törzsmókus

Antworten:

73

Der große Unterschied zwischen GWT RPC und RequestFactory besteht darin, dass das RPC-System "RPC-by-Concrete-Type" ist, während RequestFactory "RPC-by-Interface" ist.

Der Einstieg in RPC ist bequemer, da Sie weniger Codezeilen schreiben und dieselbe Klasse sowohl auf dem Client als auch auf dem Server verwenden. Sie können eine PersonKlasse mit einer Reihe von Gettern und Setzern und einer einfachen Geschäftslogik erstellen, um die Daten im PersonObjekt weiter aufzuteilen und in Würfel zu schneiden . Dies funktioniert so gut, bis Sie einen serverspezifischen, nicht GWT-kompatiblen Code in Ihrer Klasse haben möchten. Da das RPC-System darauf basiert, dass sowohl auf dem Client als auch auf dem Server derselbe konkrete Typ vorhanden ist, können Sie auf der Grundlage der Funktionen Ihres GWT-Clients auf eine Komplexitätswand stoßen.

Um die Verwendung von inkompatiblem Code zu umgehen, erstellen viele Benutzer einen Peer PersonDTO, der Persondas auf dem Server verwendete reale Objekt beschattet . Das hat PersonDTOnur eine Teilmenge der Getter und Setter des serverseitigen "Domain" Person-Objekts. Nun müssen Sie Code , dass marshalls Daten zwischen den Schreib- Personund PersonDTOObjekt und alle anderen Objekttypen , die Sie an den Client übergeben werden soll.

RequestFactory geht zunächst davon aus, dass Ihre Domänenobjekte nicht GWT-kompatibel sind. Sie deklarieren einfach die Eigenschaften, die vom Clientcode in einer Proxy-Schnittstelle gelesen und geschrieben werden sollen, und die RequestFactory-Serverkomponenten kümmern sich um das Marshalling der Daten und das Aufrufen Ihrer Dienstmethoden. Für Anwendungen mit einem genau definierten Konzept von "Entitäten" oder "Objekten mit Identität und Version" wird der EntityProxyTyp verwendet, um die persistente Identitätssemantik Ihrer Daten für den Clientcode verfügbar zu machen. Einfache Objekte werden mithilfe des ValueProxyTyps zugeordnet.

Mit RequestFactory zahlen Sie im Voraus Startkosten für kompliziertere Systeme, als GWT RPC problemlos unterstützt. RequestFactory ServiceLayerbietet deutlich mehr Hooks, um das Verhalten durch Hinzufügen von ServiceLayerDecoratorInstanzen anzupassen .

BobV
quelle
Dies ist ein guter Grund, meine Entscheidung zu unterstützen, zu RequestFactory zu wechseln. Danke, Bob! Es macht Sinn und ich verstehe nicht, warum manche Leute sagen "Verwenden Sie RPC in einigen Fällen und RF in anderen, abhängig von Ihren Anforderungen", weil es so aussieht, als müssten Sie mit RPC viel Klebercode und diese DTO-Schicht schreiben
Dan Leahu
5
Ein weiteres Plus für RequestFactory ist, dass es mit Android und GWT mit genau demselben Code verwendet werden kann.
Patrick
28

Ich habe einen Übergang von RPC zu RF durchlaufen. Zuerst muss ich sagen, dass meine Erfahrung darin begrenzt ist. Ich habe so viele EntityProxies wie 0 verwendet.

Vorteile von GWT RPC:

  • Es ist sehr einfach einzurichten, zu verstehen und zu lernen!
  • Dieselben klassenbasierten Objekte werden auf dem Client und auf dem Server verwendet.
  • Dieser Ansatz spart Tonnen von Code.
  • Ideal, wenn auf Client und Server dieselben Modellobjekte (und POJOS) verwendet werden: POJOs == MODEL OBJECTs == DTOs
  • Einfaches Verschieben von Inhalten vom Server zum Client.
  • Einfache gemeinsame Nutzung der Implementierung einer gemeinsamen Logik zwischen Client und Server (dies kann sich als kritischer Nachteil herausstellen, wenn Sie eine andere Logik benötigen).

Nachteile von GWT RPC:

  • Es ist unmöglich, einige Methoden für Server und Client unterschiedlich zu implementieren, z. B. müssen Sie möglicherweise ein anderes Protokollierungsframework für Client und Server oder eine andere Gleichheitsmethode verwenden.
  • WIRKLICH SCHLECHTE Implementierung, die nicht weiter erweiterbar ist: Der größte Teil der Serverfunktionalität wird als statische Methode in einer RPC-Klasse implementiert. DAS SAUGT WIRKLICH.
  • zB Es ist unmöglich, serverseitige Fehlerverschleierung hinzuzufügen
  • Einige Sicherheitsbedenken in Bezug auf XSS, die nicht ganz elegant lösbar sind, finden Sie in den Dokumenten (ich bin nicht sicher, ob dies für RequestFactory eleganter ist).

Nachteile von RequestFactory:

  • Wirklich schwer zu verstehen aus dem offiziellen Dokument, was ist das Verdienst davon! Es beginnt direkt bei einem völlig irreführenden Begriff PROXIES - dies sind tatsächlich DTOs von RF, die von RF automatisch erstellt werden. Proxies werden durch Schnittstellen definiert, z. B. @ProxyFor (Journal.class). IDE prüft, ob im Journal entsprechende Methoden vorhanden sind. Soviel zum Mapping.
  • RF wird in Bezug auf die Gemeinsamkeiten von Client und Server nicht viel für Sie tun, weil
  • Auf dem Client müssen Sie "PROXIES" in Ihre Clientdomänenobjekte konvertieren und umgekehrt. Das ist völlig lächerlich. Es könnte deklarativ in wenigen Codezeilen erfolgen, aber dafür gibt es KEINE UNTERSTÜTZUNG! Wenn wir unsere Domain-Objekte nur eleganter Proxys zuordnen könnten, fehlt etwas wie die JavaScript-Methode JSON.stringify (.. ,,) in der RF-Toolbox.
  • Vergessen Sie nicht, dass Sie auch dafür verantwortlich sind, übertragbare Eigenschaften Ihrer Domänenobjekte auf Proxys usw. rekursiv festzulegen.
  • POOR ERROR HANDLING auf dem Server und - Stack-Traces werden auf dem Server standardmäßig weggelassen, und auf dem Client werden leere, nutzlose Ausnahmen angezeigt. Selbst wenn ich einen benutzerdefinierten Fehlerhandler festgelegt habe, konnte ich keine Stapelspuren auf niedriger Ebene erreichen! Furchtbar.
  • Einige kleinere Fehler in der IDE-Unterstützung und anderswo. Ich habe zwei Fehleranfragen eingereicht, die akzeptiert wurden. Es wurde kein Einstein benötigt, um herauszufinden, dass es sich tatsächlich um Fehler handelte.
  • DOKUMENTATION SAUGT. Wie ich bereits erwähnt habe, sollten Proxies besser erklärt werden. Der Begriff lautet MISLEADING. Für die grundlegenden allgemeinen Probleme, die ich gelöst habe, ist DOCS USELESS. Ein weiteres Beispiel für ein Missverständnis des DOC ist die Verbindung von JPA-Anmerkungen mit RF. Aus den prägnanten Dokumenten geht hervor, dass sie irgendwie zusammen spielen, und ja, es gibt eine entsprechende Frage zu StackOverflow. Ich empfehle, jede JPA-Verbindung zu vergessen, bevor Sie RF verstehen.

Vorteile von RequestFactory

  • Hervorragende Forumunterstützung.
  • Die IDE-Unterstützung ist ziemlich gut (aber im Gegensatz zu RPC kein Vorteil)
  • Flexibilität Ihrer Client- und Server-Implementierung (lose Kopplung)
  • Ausgefallene Dinge, die mit EntityProxies verbunden sind, jenseits einfacher DTOs - Caching, Teilaktualisierungen, sehr nützlich für Mobilgeräte.
  • Sie können ValueProxies als einfachsten Ersatz für DTOs verwenden (aber Sie müssen alle nicht so ausgefallenen Konvertierungen selbst durchführen).
  • Unterstützung für Bean-Validierungen JSR-303.

Berücksichtigung anderer Nachteile von GWT im Allgemeinen:

  • Integrationstests (GWT-Clientcode + Remote-Server) mit bereitgestellter JUnit-Unterstützung können nicht ausgeführt werden. <= Alle JSNI müssen verspottet werden (z. B. localStorage). SOP ist ein Problem.

  • Keine Unterstützung für Test-Setup - Headless-Browser + Remote-Server <= Kein einfacher Headless-Test für GWT, SOP.

  • Ja, es ist möglich, Selen-Integrationstests durchzuführen (aber das ist nicht das, was ich will).

  • JSNI ist sehr mächtig, aber bei diesen glänzenden Vorträgen, die sie auf Konferenzen halten, reden sie nicht viel darüber, dass das Schreiben von JSNI-Codes einige Regeln hat. Wiederum war es eine Aufgabe eines echten Forschers, herauszufinden, wie man einen einfachen Rückruf schreibt.

Zusammenfassend ist der Übergang von GWT RPC zu RequestFactory weit entfernt von der WIN-WIN-Situation, in der RPC hauptsächlich Ihren Anforderungen entspricht. Am Ende schreiben Sie Tonnenkonvertierungen von Clientdomänenobjekten zu Proxys und umgekehrt. Sie erhalten jedoch eine gewisse Flexibilität und Robustheit Ihrer Lösung. Und die Unterstützung im Forum ist auch am Samstag hervorragend!

In Anbetracht aller Vor- und Nachteile, die ich gerade erwähnt habe, lohnt es sich, im Voraus zu überlegen, ob einer dieser Ansätze tatsächlich zu einer Verbesserung Ihrer Lösung und Ihres Entwicklungsaufbaus führt, ohne große Kompromisse einzugehen.

Honzajde
quelle
Kasse JBoss Erai. Ich liebe ihre Herangehensweise an RPC.
Καrτhικ
6

Ich finde die Idee, Proxy-Klassen für alle meine Entitäten zu erstellen, ziemlich ärgerlich. Meine Hibernate / JPA-Pojos werden automatisch aus dem Datenbankmodell generiert. Warum muss ich jetzt einen zweiten Spiegel für RPC erstellen? Wir haben ein schönes "Estivation" -Rahmenwerk, das sich um das "Entschlafen" der Pojos kümmert.

Auch die Idee, Dienstschnittstellen zu definieren, die den serverseitigen Dienst nicht ganz als Java-Vertrag implementieren, aber die Methoden implementieren, klingt für mich sehr nach J2EE 1.x / 2.x.

Καrτhικ
quelle
5
Es ist ärgerlich, aber wenn Sie trotzdem Proxys erstellen müssen, möchten Sie lieber die zusätzliche Hilfe, die RF Ihnen für die Verwaltung dieser Proxys bietet. Nicht jeder möchte das gesamte Pojo an den Kunden senden - zum Beispiel ein Pokerspiel - Ihr Player-Objekt enthält möglicherweise Informationen, die jeder sehen sollte (Anzahl der Karten in der Hand, Karten, die offen liegen, Gesamtchips) und andere Informationen, die nur vorhanden sind Ein Spieler sollte sehen (verdeckte Karten).
Peter Recore
Ihr Poker-Beispiel ist gültig - wir umgehen dies, indem wir Anmerkungen (@WireTransient) verwenden, die unser "Estivation" -Framework verwendet, um Werte zu unterdrücken.
Καrτhικ
4

Im Gegensatz zu RequestFactory mit schlechten Funktionen zur Fehlerbehandlung und zum Testen (da die meisten Dinge unter der Haube von GWT verarbeitet werden) können Sie mit RPC einen serviceorientierteren Ansatz verwenden. RequestFactory implementiert einen moderneren Ansatz im Stil der Abhängigkeitsinjektion, der einen nützlichen Ansatz bietet, wenn Sie komplexe polymorphe Datenstrukturen aufrufen müssen. Wenn Sie RPC verwenden, müssen Ihre Datenstrukturen flacher sein, da dies Ihren Marshalling-Dienstprogrammen ermöglicht, zwischen Ihren json / xml- und Java-Modellen zu übersetzen. Mit RPC können Sie auch eine robustere Architektur implementieren, wie im Abschnitt gwt dev auf der Google-Website angegeben.

"Einfache Client / Server-Bereitstellung

Die erste und einfachste Möglichkeit, sich Service-Definitionen vorzustellen, besteht darin, sie als das gesamte Back-End Ihrer Anwendung zu behandeln. Aus dieser Perspektive ist clientseitiger Code Ihr "Front-End" und der gesamte auf dem Server ausgeführte Service-Code ist "Back-End". Wenn Sie diesen Ansatz wählen, handelt es sich bei Ihren Service-Implementierungen in der Regel um allgemeinere APIs, die nicht eng an eine bestimmte Anwendung gekoppelt sind. Ihre Dienstdefinitionen greifen wahrscheinlich direkt über JDBC oder Hibernate oder sogar auf Dateien im Dateisystem des Servers auf Datenbanken zu. Für viele Anwendungen ist diese Ansicht geeignet und kann sehr effizient sein, da sie die Anzahl der Ebenen verringert.

Multi-Tier-Bereitstellung

In komplexeren, mehrstufigen Architekturen können Ihre GWT-Dienstdefinitionen einfach einfache Gateways sein, die Back-End-Serverumgebungen wie J2EE-Server aufrufen. Aus dieser Perspektive können Ihre Dienste als "Serverhälfte" der Benutzeroberfläche Ihrer Anwendung angesehen werden. Anstatt universell zu sein, werden Dienste für die spezifischen Anforderungen Ihrer Benutzeroberfläche erstellt. Ihre Dienste werden zum "Front-End" für die "Back-End" -Klassen, die durch Zusammenfügen von Aufrufen an eine allgemeinere Back-End-Schicht von Diensten geschrieben werden, die beispielsweise als Cluster von J2EE-Servern implementiert sind. Diese Art von Architektur ist geeignet, wenn Ihre Back-End-Dienste auf einem physisch von Ihrem HTTP-Server getrennten Computer ausgeführt werden müssen. "

Beachten Sie auch, dass zum Einrichten eines einzelnen RequestFactory-Dienstes etwa 6 Java-Klassen erstellt werden müssen, für die als RPC nur 3 erforderlich sind. Mehr Code == mehr Fehler und Komplexität in meinem Buch.

RequestFactory hat auch etwas mehr Overhead während der Anforderungsverarbeitung, da die Serialisierung zwischen den Datenproxys und den tatsächlichen Java-Modellen gemarshallt werden muss. Diese zusätzliche Schnittstelle fügt zusätzliche Verarbeitungszyklen hinzu, die sich in einer Unternehmens- oder Produktionsumgebung wirklich summieren können.

Ich glaube auch nicht, dass RequestFactory-Dienste Serialisierung wie RPC-Dienste sind.

Alles in allem, nachdem ich beide seit einiger Zeit verwendet habe, verwende ich RPC immer als leichter, einfacher zu testen und zu debuggen und schneller als mit einer RequestFactory. Obwohl RequestFactory möglicherweise eleganter und erweiterbarer ist als sein RPC-Gegenstück. Die zusätzliche Komplexität macht es nicht zu einem besseren Werkzeug.

Meiner Meinung nach besteht die beste Architektur darin, zwei Web-Apps, einen Client und einen Server, zu verwenden. Der Server ist eine einfache, leichtgewichtige generische Java-Webanwendung, die die Bibliothek servlet.jar verwendet. Der Kunde ist GWT. Sie stellen eine RESTful-Anforderung über GWT-RPC auf der Serverseite der Client-Webanwendung. Die Serverseite des Clients ist jedoch nur ein Durchgang zum Apache-HTTP-Client, der einen dauerhaften Tunnel in den Anforderungshandler verwendet, den Sie als einzelnes Servlet in Ihrer Server-Servlet-Webanwendung ausführen. Die Servlet-Webanwendung sollte Ihre Datenbankanwendungsschicht enthalten (Ruhezustand, Cayennepfeffer, SQL usw.). Auf diese Weise können Sie die Datenbankobjektmodelle vollständig vom eigentlichen Client trennen und so Ihre Anwendung wesentlich erweiterbarer und robuster entwickeln und testen. Zugegeben, es erfordert ein bisschen anfängliche Einrichtungszeit. Am Ende können Sie jedoch eine dynamische Anforderungsfactory außerhalb von GWT erstellen. So können Sie das Beste aus beiden Welten nutzen. Ganz zu schweigen davon, dass Sie Ihre Serverseite testen und Änderungen daran vornehmen können, ohne dass der GWT-Client kompiliert oder erstellt werden muss.

1-14x0r
quelle
0

Ich denke, es ist wirklich hilfreich, wenn Sie auf der Clientseite ein starkes Pojo haben, zum Beispiel wenn Sie Hibernate- oder JPA-Entitäten verwenden. Wir haben eine andere Lösung gewählt, die ein Persistenz-Framework im Django-Stil mit sehr leichten Einheiten verwendet.

Uberto
quelle
0

Die einzige Einschränkung, die ich einfügen würde, ist, dass RequestFactory den binären Datentransport (deRPC vielleicht?) Und nicht den normalen GWT-RPC verwendet.

Dies ist nur wichtig, wenn Sie umfangreiche Tests mit SyncProxy, Jmeter, Fiddler oder einem ähnlichen Tool durchführen, das den Inhalt der HTTP-Anforderung / Antwort lesen / auswerten kann (wie GWT-RPC), mit deRPC oder RequestFactory jedoch eine größere Herausforderung darstellen.

Dhartford
quelle
1
Abgesehen davon, dass RequestFactory eine sofort einsatzbereite "reine Java" -Implementierung bietet, ohne dass Tools von Drittanbietern wie SyncProxy erforderlich sind. Siehe stackoverflow.com/questions/4853188/…
Thomas Broyer
0

Wir haben eine sehr große Implementierung von GWT-RPC in unserem Projekt. Tatsächlich haben wir 50 Service-Schnittstellen mit jeweils vielen Methoden, und wir haben Probleme mit der Größe der vom Compiler generierten TypeSerializer, die unseren JS-Code riesig machen. Wir analysieren also, um auf RequestFactory umzusteigen. Ich bin seit ein paar Tagen gelesen worden, habe mich im Internet umgesehen und versucht herauszufinden, was andere Leute tun. Der wichtigste Nachteil, den ich gesehen habe, und vielleicht könnte ich mich irren, ist, dass Sie mit RequestFactory nicht mehr die Kontrolle über die Kommunikation zwischen Ihren Server Domain-Objekten und Ihren Client-Objekten haben. Wir müssen das Lade- / Speichermuster kontrolliert anwenden. Ich meine, zum Beispiel empfängt der Client das gesamte Objektdiagramm von Objekten, die zu einer bestimmten Transaktion gehören, führt seine Aktualisierungen durch und sie senden das gesamte an den Server zurück. Der Server ist für die Validierung verantwortlich, vergleicht alte mit neuen Werten und führt die Persistenz durch. Wenn 2 Benutzer von verschiedenen Sites dieselbe Transaktion erhalten und einige Aktualisierungen vornehmen, sollte die resultierende Transaktion nicht die zusammengeführte sein. Eines der Updates sollte in meinem Szenario fehlschlagen. Ich sehe nicht, dass RequestFactory diese Art der Verarbeitung unterstützt.

Grüße Daniel

Daniel Ardison
quelle
Ich teile diese Bedenken ... sind Sie mit RF gelandet?
HDave
0

Ist es fair zu sagen, dass es bei der Betrachtung einer eingeschränkten MIS-Anwendung, beispielsweise mit 10-20 CRUD-fähigen Geschäftsobjekten und jeweils mit ~ 1-10 Eigenschaften, wirklich auf die persönlichen Vorlieben ankommt, welchen Weg man einschlägt?

Wenn ja, könnte die Projektion der Skalierung Ihrer Anwendung möglicherweise der Schlüssel für die Auswahl Ihrer Route GWT RPC oder RequestFactory sein:

  1. Es wird erwartet, dass meine Bewerbung bei dieser relativ begrenzten Anzahl von Unternehmen bleibt, aber in Bezug auf ihre Anzahl massiv zunimmt. 10-20 Objekte * 100.000 Datensätze.

  2. Meine Bewerbung wird in der Breite der Entitäten erheblich zunehmen, aber die relativen Zahlen der einzelnen Entitäten werden niedrig bleiben. 5000 Objekte * 100 Datensätze.

  3. Es wird erwartet, dass meine Anwendung bei dieser relativ begrenzten Anzahl von Entitäten bleibt UND in einer relativ geringen Anzahl von z. B. 10-20 Objekten * 100 Datensätzen bleibt

In meinem Fall bin ich am Anfang des Versuchs, diese Entscheidung zu treffen. Noch komplizierter, da die clientseitige Architektur der Benutzeroberfläche geändert und die Transportauswahl getroffen werden muss. Meine vorherige (signifikant) groß angelegte GWT-Benutzeroberfläche verwendete die Hmvc4Gwt-Bibliothek, die durch die GWT-MVP-Einrichtungen ersetzt wurde.

kühler Löffel
quelle