Vor einiger Zeit haben ein Kollege und ich beschlossen, eine Anwendung mit Grails und Eclipse RCP zu schreiben. Wir haben uns für Grails entschieden, weil die Entwicklung so einfach ist, und für Eclipse RCP (anstelle von Flex und Plain Old HTML), weil wir unseren Benutzern ein solides und natives Look and Feel bieten wollten, wofür Eclipse RCP sehr gut geeignet ist.
Da das Eclipse RCP-Frontend tatsächlich ein Remote-Frontend sein würde, benötigten wir eine Art der Kommunikation zwischen dem Client und dem Server. Eine unserer ersten Ideen war die Verwendung von XML-RPC, das in Grails ziemlich gut unterstützt wird, uns aber dazu zwingen würde, ein Mapping zwischen unserer Domain und dem XML vorzunehmen. Da wir in Eclipse dieselben Domänenklassen wie in Grails verwenden wollten (indem wir die Grails-Domäne in externe Domänen-Jars exportieren), haben wir uns für einen anderen Ansatz entschieden: Burlap/Hessian.
Sackleinen/Hessisch
Burlap und Hessian sind zwei von Caucho entwickelte Protokolle. Sie dienen demselben Zweck, aber Burlap ist XML, während Hessian binär ist. Obwohl es eigentlich keinen Grund gibt, Burlap zu verwenden, da Hessian viel kleiner und damit schneller ist, entscheiden wir uns für Burlap, da es einfacher zu debuggen ist (es ist schließlich einfaches XML). Okay, es gibt also doch einen Grund, Burlap zu wählen...
In unserer Eclipse RCP-Anwendung könnten wir Spring verwenden, das von Haus aus Unterstützung für Hessian und Burlap bietet. In Grails könnten wir das Grails Remoting Plugin verwenden, das ebenfalls Unterstützung für Burlap und Hessian (und HttpInvoker und RMI, aber dazu später mehr) bietet. Wir brauchten also nur ein wenig zu konfigurieren, sie miteinander zu verbinden, und es würde ohne Probleme funktionieren. Richtig? Richtig! In der Theorie sollte es sofort funktionieren. In der Praxis gab es Hibernate. Und Proxies. Und auch einige Bugs....
Winterschlaf
Grails verwendet Hibernate. Das ist kein Problem, im Gegenteil, es ist großartig! Warum das Rad neu erfinden, wenn es ein leistungsstarkes Framework gibt? Es gibt jedoch einige Probleme bei der Verwendung von Hibernate in Kombination mit Remoting. Das ist nicht Grails-spezifisch, aber es trat in unserer Anwendung auf, und da unsere Anwendung eine Grails-Anwendung war, hat es uns beunruhigt! Das Problem bei der Verwendung von Grails ist jedoch, dass Sie möglicherweise nicht vermuten, dass alle von Ihnen verwendeten Sammlungen tatsächlich Hibernate-Sammlungen sind. Normalerweise spielt das in einer Webanwendung keine Rolle: Hibernate-Sammlungen funktionieren wie jede andere Sammlung. Beim Remoting sieht die Sache jedoch ein wenig anders aus...
ClassNotFoundException für Hibernate-Listen
Da Sie Hibernate und Remoting verwenden, benötigen Sie Hibernate auf der Client-Seite wegen der Hibernate Collections. Entweder das, oder Sie erstellen selbst Kopien der Objekte. Wenn Sie schon dabei sind, können Sie auch DTOs dafür erstellen, die zusätzliche Vorteile bieten. Allerdings bedeutet dies eine Menge zusätzlicher Arbeit (manuelles Kopieren, zusätzliche zu pflegende Klassen usw.), so dass wir dies lieber nicht tun sollten.
Ausnahme bei träger Initialisierung / Proxies
Eine einfache Lösung für die oben genannten Probleme ist natürlich, die Bibliotheken auf dem Client zu erweitern. Vielleicht nicht die beste Lösung, aber eine Lösung ist es allemal. Wenn Sie jedoch die Bibliotheken auf dem Client haben, kann es wegen der Hibernate-Proxys zu Ausnahmen bei der Initialisierung kommen. Die einfachste Lösung besteht darin, sich darauf zu einigen, was abgerufen werden soll, alle Entitäten eifrig abzurufen und nur auf die Beziehungen zuzugreifen, auf die Sie sich geeinigt haben. Es gibt (natürlich!) ein kleines Problem mit diesem Ansatz: Standardmäßig holt Hibernate outer joins 'nur' 3 Ebenen tief, aber ich brauchte 4. Die empfohlenen Werte liegen zwischen 0 und 3, aber es gibt nicht viele Daten zu übertragen, also habe ich die hibernate.max_fetch_depth Eigenschaft in Grails auf 4 gesetzt. Das hat vieles gelöst! Aber leider nicht alles...
Grails-Fehler
Wie es scheint, gibt es eine Menge Leute, die Grails für die Erstellung von Webanwendungen verwenden, aber nur wenige von ihnen verwenden Grails für etwas anderes, wie z.B. Remoting. Es waren nicht viele Informationen zu finden, außer im Wiki, und es gab ein kleines Problem: es funktionierte nicht. Nach 2 Tagen der Programmierung habe ich mehr als 5 Jira-Probleme zum Thema Remoting erstellt (siehe zum Beispiel hier, , oder hier . Die meisten Probleme waren Blocker für Hessian und Burlap oder verursachten eine Menge Lärm, der das eigentliche Problem verbarg. Nach ein paar Tagen ohne große Fortschritte mussten wir also reden...
Alternativen
Nach 2 Tagen mit Remoting-Problemen standen wir an einer T-Kreuzung, an der wir entweder nach links oder nach rechts gehen konnten. Links würde bedeuten: nach völlig anderen Möglichkeiten für das Remoting zu suchen, wie XML-RPC oder SOAP, und rechts würde bedeuten: unsere 2 alternativen Remoting-Optionen zu untersuchen: RMI und HttpInvoker. Nach einigen Diskussionen haben wir beschlossen, HttpInvoker eine letzte Chance zu geben: RMI ist nicht Firewall-freundlich, und XML-RPC/SOAP würde eine Menge zusätzlicher Arbeit bedeuten. Und endlich hatten wir Erfolg!
HttpInvoker
HttpInvoker ermöglichte es uns, unsere Tests zu bestehen! Das bedeutete, dass es möglich war, ein einzelnes Objekt oder eine Liste von Objekten abzurufen und Informationen an den Server zu senden! Das funktionierte großartig, alle unsere Tests bestanden! Und wir lebten glücklich bis ans Ende unserer Tage.... oder etwa nicht? Ich habe vergessen, 1 weiteren Test zu implementieren: das Speichern eines komplexen Objekts (wie eine Project-Klasse, die zwei Strings enthält). Etwas mit einer ClassNotFoundException, obwohl wir wussten, dass unsere Klassen vorhanden waren..
Fazit
Trotz all unserer Probleme mit Grails, den Fehlern, dem Remoting, mit allem, war es eine großartige Lernerfahrung. Wenn alle Bugs behoben sind, wird Grails sein Versprechen, ein hochproduktives Framework zu sein, wirklich einlösen. Es ist wirklich keine Konfiguration erforderlich, und wenn es funktioniert, ist es großartig. Ich würde auf jeden Fall etwas wie HttpInvoker verwenden, um das Remoting in Zukunft durchzuführen. Es funktioniert (im Moment) am besten, kann Firewalls problemlos überwinden und wird gut unterstützt (sowohl in Spring als auch in Grails). Und vor allem hat es trotz einiger Frustrationen mit dem Remoting-Plugin wirklich Spaß gemacht, die Anwendung zu entwickeln!
Update
Während ich diesen Blog schrieb, erhielt ich einige Status-Updates zu den restlichen Problemen, die nun alle behoben zu sein scheinen! Es wurde sogar eine neue Version des Plugins veröffentlicht! Das ist ein Teil der Stärke der Grails Community: kein Framework ist 100%ig korrekt oder fehlerfrei, aber es ist großartig, dass es Leute wie Peter Ledbrook gibt, die sich darum kümmern, Grails noch besser zu machen. Nochmals vielen Dank, Peter, Ihre Unterstützung ist großartig!
Verfasst von
Erik Pragt
Unsere Ideen
Weitere Blogs
Contact



