Dienstag, 4. August 2009

RichTextEditor in GWT

Ich habe mich sehr gefreut, dass GWT auch einen komfortablen Texteditor bereitstellt. Die Widget Gallery enthält einen Screenshot, der Showcase tatsächlich eine funktionierende Version. Die Ernüchterung kommt dann leider recht schnell, wenn man den RichTextEditor selbst einsetzen möchte: Ausser einer leeren TextArea gibts da nicht viel. Wo sind die Buttons? Ein Blick in die Sourcen des Showcase zeigt wie der RTE konfiguriert wird:

@Override
public Widget onInitialize() {
// Create the text area and toolbar
RichTextArea area = new RichTextArea();
area.ensureDebugId("cwRichText-area");
area.setSize("100%", "14em");
RichTextToolbar toolbar = new RichTextToolbar(area);
toolbar.ensureDebugId("cwRichText-toolbar");
toolbar.setWidth("100%");

// Add the components to a panel
Grid grid = new Grid(2, 1);
grid.setStyleName("cw-RichText");
grid.setWidget(0, 0, toolbar);
grid.setWidget(1, 0, area);
return grid;
}



Die Klasse RichTextToolbar findet sich jedoch nirgendwo im GWT.
Will man einen funktionierenden RTE einsetzen bleibt einem nichts anderes übrig als die Klasse aus dem Showcase zu übernehmen und ggf. anzupassen. So gehts:

  1. Im Verzeichnis samples\Showcase\src\com\google\gwt\sample\showcase\client\content\text des GWT alle Grafiken sowie RichTextToolbar.java und RichTextToolbar$Strings.properties ins Package toolbar im Client-Package des GWT-Projektes kopieren.
  2. Package-Deklaration in RichTextToolbar.java anpassen.
  3. Optional: Der Konstruktor enthält die Deklaration aller Buttons und Auswahllisten. Was nicht benötigt wird auskommentieren.
  4. Im Clientcode: RichTextEditor instantiieren und an Konstruktor der RichTextToolbar übergeben.
  5. Sowohl Editor als auch Toolbar einem Panel hinzufügen. Hier ein Beispiel:



RichTextArea area = new RichTextArea();
RichTextToolbar toolbar = new RichTextToolbar(area);
RootPanel.get("rte").add(toolbar);
RootPanel.get("rte").add(area);

Donnerstag, 30. Juli 2009

Trouble mit GWT und der Google App Engine

Wer schonmal erste Schritte mit dem GWT gemacht hat und das ganze auf der Google App Engine deployen wollte kennt das:

No source code is available for type javax.jdo.PersistenceManagerFactory; did you forget to inherit a required module?

Der GWT-Compiler übersetzt den gesamten Client-Code (d.h. alles was entweder im Client Package des Moduls liegt oder von einer Klasse aus diesem Package referenziert wird) in JavaScript. Dazu wird der Source-Code benötigt, der aber für die JDO Implementierung nicht vorliegt. Der PersistenceManager von JDO macht dann Probleme, wenn man nicht vorher

Nach einigem googlen habe ich 3 Lösungsansätze gefunden:
  1. Von JDO auf JPA schwenken
  2. Mit DTO's arbeiten
  3. Vernünftige Projektstruktur (wer hätte das gedacht?!)
1) Bringt uns nicht weiter, da dem GAE-Datastore keine relationale Datenbank zugrundeliegt und somit einige relationale Features nicht verfügbar sind. Wozu also JPA verwenden?

2) Naaah, dann müssen ja immer zwischen den Services und der tatsächlichen Oberfläche Objekte umgebaut werden

3) Denken wir nochmal nach: Die POJO's liegen letztlich in einem Client-Package oder werden zumindest vom Client-Code referenziert, da sie unser BusinessModell darstellen. Was aber haben Persistenz-Manager dort verloren? Richtig, garnix, die PersistenceManagerFactory wird in das Server-Package verschoben (schliesslich kümmert sich die Service-Implementierung um die Kommunikation mit dem Persistenzkontext).

Siehe da, es läuft.

Wie man das Businessmodell in ein eigenes Modul auslagert wird hier recht gut erklärt.

[Update 31.07.09]
Leider gibt es in der derzeit aktuellen Version Probleme mit der GWT<->GAE Integration.
Es ist schlicht nicht möglich Clientseitig Code zu verwenden, der aus org.datanucleus.store.appengine* stammt. Unter der Verwendung von POJO's als Domänenklassen führt das spätestens wenn das Ergebnis einer Abfrage dargestellt werden soll zu Problemen. Dieser Post beschreibt das Problem etwas ausführlicher

Es gibt einen Workaround der allerdings zur Folge hat, dass die Anwendung sich selbst um die Verwaltung der Primärschlüssel kümmern muss und (noch schlimmer) nur mit transienten Objekten gearbeitet werden kann.

Die Verwendung von DTO's scheint also zur Zeit der einzig gangbare Weg zu sein.

Hallo, jemand zuhause?

Hallo, Welt!
Hier kommen dann alle Beiträge rein, die ich loswerden will, die sonst nirgendwo reinpassen oder die schlicht zu lang zum twittern sind.