# Architektur GWT + EJB



## shinjy (1. Dez 2011)

Hallo,

ich habe mal eine Frage zur Realisierung folgender Architektur.
Mein Projekt besteht zum einen aus einem GWT Package, dass wiederum aus einem Client Package und einem Servlet besteht und zum anderen aus einem EJB Package, indem sich Session Beans zur Verwaltung  von Persistence Entities befinden.
Das ganze läuft auf einem Glassfish.
Nachfolgend die Beispielklassen aus dem EJB Package und das GWT Servlet:

Entities + Session Bean:
[Java] EJB - Pastebin.com

GWT Servlet:
[Java] gwt servlet - Pastebin.com


Nun meckert Eclipse natürlich im Servlet das die Klasse Company nicht bekannt ist. jedoch sollte es möglich sein, dass das beispiel Objekt Company mitsamt seiner Referenzen zwischen GWT Client und MYSQL Datenbank hin und her geschickt werden kann. Nun frage ich mich aber wie man dieses am besten bewerkstelligt. Die beiden Klassen in ein Jar verpacken und in das GWT Projekt importieren funktioniert jedenfalls nicht. Stehe da gerade auffem Schlauch und bin auf diesem Gebiet noch nicht wirklich erfahren.
Zudem habe ich gelesen das das GWT an dieser Stelle Probleme bereitet. Stimm dies und wenn ja wie kann man das lösen?

Wäre nett wenn mir mal jemand einen kleinen Hinweis geben kann.


----------



## JohannisderKaeufer (2. Dez 2011)

Um genaueres nicht sagen zu können wäre, die *gwt.xml noch von interesse.

Dort gibt es typischerweise diese Zeilen.
[XML]  <!-- Specify the paths for translatable code                    -->
  <source path='client'/>
  <source path='shared'/>
[/XML]

In einem dieser Ordner sollte, die Klasse Company liegen, da sie sonst vom GWT-Compiler angemeckert wird.

Außerdem finden sich noch diese Zeilen in der gwt.xml
[XML]  <!-- Inherit the core Web Toolkit stuff.                        -->
  <inherits name='com.google.gwt.user.User'/>

  <!-- Inherit the default GWT style sheet.  You can change       -->
  <!-- the theme of your GWT application by uncommenting          -->
  <!-- any one of the following lines.                            -->
  <inherits name='com.google.gwt.user.theme.clean.Clean'/>
  <!-- <inherits name='com.google.gwt.user.theme.standard.Standard'/> -->
  <!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> -->
  <!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/>     -->

  <!-- Other module inherits                                      -->
[/XML]

Über die gwt.xml sollte sich aber vorerst ausreichend Doku finden lassen.


----------



## shinjy (2. Dez 2011)

Hallo,
vielen Dank schon einmal für deine Antwort.



JohannisderKaeufer hat gesagt.:


> Um genaueres nicht sagen zu können wäre, die *gwt.xml noch von interesse.
> 
> Dort gibt es typischerweise diese Zeilen.
> [XML]  <!-- Specify the paths for translatable code                    -->
> ...



Da liegt ja genau mein Problem. Die Klassen sollen ja als Entities in einer Datenbank gespeichert werden und aus diesem Grund müssen sie ja als Persistence Entities in dem EJB Project definiert sein. 
Wie soll diese dann im GWT Projekt im shared Ordner liegen?
Oder meinst du das man z.B. die Klasse Company im gwt.xml definieren könnte und so das GWT Projekt etwas mit den übermittelten Objekten aus dem EJB Projekt etwas anfangen kann?


----------



## JohannisderKaeufer (2. Dez 2011)

In deinem ersten Post sprichst du von packages im zweiten von Projekten. Da gibt es feine Unterschiede.

Ausführlich:

8. Using external jars / Java projects in GWT

Kurzform:

Im EJB Project benötigst du eine gwt.xml mit unter anderem 

[XML]<module><source path="ordnerInDemDieEJBsLiegen"></source></module>[/XML]

Im GWT Project in der gwt.xml

[XML]<inherits name='package.in.dem.die.Ejbs.liegen'/>[/XML]

Compilieren und hoffen, dass alles glatt läuft.

Du mußt sozusagen, neben der Class und Buildpath-Verwaltung die du bei einem üblichen Java-Projekt machst, zusätzlich den Buildpath für den GWT-Client in den gwt.xml Dateien manuell ergänzen.


----------



## shinjy (2. Dez 2011)

Vielen Dank schon einmal für deine Mühe.

Leider bekomme ich immer folgende Exception, obwohl ich die Anleitung befolgt habe:

```
Loading inherited module 'de.vogella.gwt.module.model'
   [ERROR] Unable to find 'de/vogella/gwt/module/model.gwt.xml' on your classpath; could be a typo, or maybe you forgot to include a classpath entry for source?
```

Ich vermute aber auch, da meine Entities im EJB Projekt logischerweise Annotationen beinhalten, das spätestens dann der GWT Compiler gestreikt hätte und ich die Klassen nicht benutzen könnte.

Eine Lösung wäre der Einsatz von DTO's, welche ich aber nur ungern einsetzen würde.

Habe gerade auch noch die RequestFactory entdeckt. hat damit schon jemand Erfahrung?


----------



## JohannisderKaeufer (2. Dez 2011)

Naja, die Fehlermeldung ist doch schon aussagekräftig.


```
Loading inherited module 'de.vogella.gwt.module.model'
   [ERROR] Unable to find 'de/vogella/gwt/module/model.gwt.xml' on your classpath; could be a typo, or maybe you forgot to include a classpath entry for source?
```

*Erstens*
wenn du in deiner client*.gwt.xml-Datei

```
<inherit name='de.vogella.gwt.module.model' />
```

stehen hast brauchst du eine Datei 
model.gwt.xml

Diese muß in dem Projekt unter src/de/vogella/gwt/module/ liegen.

*Zweitens*

Mußt du das Projekt in Eclipse mit Rechtsclick> Properties> Java Build Path> Projects > Add hinzufügen, wenn noch nicht geschehen.

Dann wird auch die benötigte model.gwt.xml Datei gefunden und es kompiliert. 

Hab ich soeben ausprobiert. Und es funktioniert. Sollte Zweitens nicht gemacht worden sein, kommt genau diese Fehlermeldung.

Poste doch mal deine gwt.xml Dateien, Ordnerstruktur wo diese liegen und wie ein Projekt das andere Referenziert!


----------



## shinjy (2. Dez 2011)

Hallo,

mittlerweile klappt es. Ich war ein wohl ein bischen von der ganzen Struktur verwirrt gewessen.
Ich habe es jetzt soweit, dass ich ein Objekt im Clienten erstellen kann, es per GWT Servlet an eine SessionBean schicken kann um es dann anschließend in einer MYSQL Datenbank zu speichern.
Nun wollte ich gerade ein Objekten von der Sessionbean zurück an den GWT Client schicken. Ärgerlicherweise bekomme ich immer folgende Exception:

```
com.google.gwt.user.client.rpc.SerializationException: Type 'org.eclipse.persistence.indirection.IndirectList' was not included in the set of types which can be serialized by this SerializationPolicy or its Class object could not be loaded. For security purposes, this type will not be serialized.: instance = {IndirectList: not instantiated}
```

Hier scheint das GWT wohl zu streiken. Hat hier jemand eine Idee wie man dieses Problem lösen kann?
Habe das hier dazu gefunden:
jpa 2.0 - entity with relationships through GWT RPC problem - Stack Overflow

Scheint wohl DTO's hinauszulaufen. Schade..


----------



## JohannisderKaeufer (3. Dez 2011)

So wie ich das sehe hat eine deiner Entities eine java.util.List.

Wenn du im Code nun eine ArrayList instanziierst, kann das als List in der Datenbank abgelegt werden.

Das Problem ist, wenn du wieder aus der Datenbank liest. Dann kann das JPA-Framework einen anderen Datentyp wählen, den es als besser erachtet.

in dem Falle org.eclipse.persistence.indirection.IndirectList. 
IndirectList, wie auch IndirectMap arbeiten allerdings anders als eine ArrayList.

wenn du deine Entity aus der DB holst, werden die Daten die in der List stehen nicht mitgeliefert, sondern es wird eine "Verknüpfung" mitgeliefert in der steht, wie man die Daten aus der DB bekommen kann. Das macht das ganze sehr Performant, wenn man auf die Daten in der List momentan nicht zugreifen braucht.

Erst wenn man tatsächlich auf die List zugreift, werden die Daten aus der DB bezogen und dann im Speicher abgelegt/gecacht.

D.h. wenn du dein Objekt serialisierst (für den Client), dann hast du erstmal nur eine Verknüpfung auf die Datenbankabfrage. Der Client, der ja prinzipiell ein anderer Rechner ist als der Server, müßte dann eine Verbindung zur DB bekommen, was ja eigentlich nicht gewünscht ist.


Es gibt aber einen Workaround für das ganze. Den gibt es in spanisch? zum nachlesen Optsicom EAW - Serialización de JPA en GWT - SidelabCode - The sidelab forge

Die Esssenz daraus ist, dass du sowas brauchst


```
@PostLoad
public void fix(){
List temp = new ArrayList(this.list);
this.list = temp
}
```

Für eine Map entsprechend.

Ich kann mir auch vorstellen, dass wenn man bei Listen und maps, (Collections allgemein) den FetchType explizit auf Eager setzt, dass dann auf eine IndirectList verzichtet wird und ein anderer Datentyp gewählt wird. Denn der Sinn und Zweck von einer IndirectList ist ja nichts anderes als Lazy-Fetching.

Also FetchType.EAGER würde ich als erstes versuchen, dann eventuell das mit dem PostLoad und wenn das nicht hinhaut, sind wohl DTO's angesagt.

Edit: Kann man den Datentyp nicht auch per Annotation fest setzen? Finde darüber gerade nichts, vielleicht weiß da aber jemand anders drüber bescheit.


----------



## shinjy (4. Dez 2011)

Also habe jetzt folgendes an meiner Entity Klasse geändert:


```
@OneToMany(cascade={CascadeType.PERSIST},
			fetch = FetchType.EAGER)
	private Collection<Person> personen = new Vector<Person>();
```


Und voilá es funktioniert. Jetzt bin ich in der Lage Objekte mitsamt deren Referenzen zu persistieren
und auch dem Clienten verfügbar zu machen.
Nun gilt es mein Modell umzustellen, aber die Grundvorraussetzungen sind so schon einmal gegeben.
Vielen Dank für deine ausführliche Hilfe!


----------

