RCP EJB3 Remote Collection -> InvocationException

maksbor80

Mitglied
Hallo Leute,

ich habe folgendes Problem.
Eclipse RCP Client versucht eine Funktion von einem Service über JNDI aufzurufen. Die Funktion liefer eine Liste von serialisierten Objecten zurück. Die serialisierbare objecte haben als Atribut eine Collection von anderen serialisierbaren Objecten. So.
Die Liste kommt beim Client an, aber die interne Collection nicht. Wenn ich in Debug Modus auf dem client in die Collection rein schue, da steht "persistentBag -> com.sun.jdi.InvocationException"
Die Collections sind in den Entitys als ArrayListen implimentiert.

PHP:
@OneToMany(cascade = CascadeType.ALL)
	@JoinTable(name="b_a")
	private Collection<EinObject> a = new ArrayList<EinObject>();

Hilfe
 
Was hast du denn als JPA Persistence Provider? Hibernate erzeugt zur Laufzeit Proxies, die Collections lazy nachladen. Wenn die Instanz dann auf dem Client ist, ist natürlich die Hibernate Session weg.

Du solltest dem Client eher DTOs liefern und diese auf Serverseite entsprechend vorbereiten (Collections laden usw.).

Gruß
Ollie
 
Danke Oliver.

Ich verwende Hibernate.

Ich bin etwas skäptisch gegenüber deinem Ansatz. Ich will auf DTOs verzichten und die Entities durch die Leitung schieben.
Ich sehe da eine Möglichkeiten, die mir vernünftig erscheint:
ich nehme anstatt Collections einfach Arrays und vergesse das Problem, da muss ich aber IndexSpalte für die Sortierung in der DB-Tabelle mitschleppen.
Hat jemand noch ideen. Das kann doch nicht sein das EJB3 auch das vergessen hat.?

Als Anekdote:
Ich habe da etwas seltsames erlebt. Beim debugen der Funktion auf Serverseite habe ich folgendes beobachten können. Wenn ich vor dem return in die Collection-Atribut etwas tiefer rein schaue, dann kann ich die Objekte sehen. Dann returne ich und schaue in die Collections-Attribute, wahnsinn, ich sehe sie, aber nur in den Collections-Attributen, die ich auf der Serverseite geschaut habe. Wenn ich auf der Serverseite alle öffne im debug, dann ist alles so, wie es sein muss. Dazu muss ich sagen, dass beide auf einem Rechner laufen. Cleint greift aber per RemoteInterface auf localhost zu.
Entweder kann er die Collections automatisch nachladen, wenn ich in sie schaue, oder Eclipse merkt sich die, da alles in eclipse gestartet wird.

danke
 
Ich weiß nicht, ob dich der Typwechsel weiterbringt. Zum einen löst das nicht die LazyLoading Problematik, zum anderen halte ich es für falsch, mir von der Persistenzschicht in mein Domänenmodell reinreden zu lassen.

Das einzige was du tun kannst, ist halt jegliche Relationen eager zu laden. Bzw. vor dem "versenden" der Entitäten explizit die Getter der Relationen zu rufen, was dann das LazyLoading triggert. Wie gesagt, Hibernate Domänenklassen machen im Remoting eigentlich immer Probleme. Zudem ist das DTO ein etabliertes Pattern um den Client nicht zu stark an den Server zu koppeln. Ohne DTOs schlägt jede Änderung am Domänenmodell sofotr auf den Client durch. Ich präferiere das Entwicklungsmodell ohne DTOs auch, allerdings nur für Anwendungen, in denen Client und Server in der gleichen VM laufen (Webanwendung auf Tomcat z.B.).

Wieviele Rechner das sind ist btw. egal. Sobald die zweite VM dazu kommt musst du remoten und die ganzen Problemchen, die das mit sich bringt sind da.

Zu deiner Debug Anekdote. Das klingt ziemlich logisch. Durch das Anschauen im Eclipse Debug Modus triggerst du das dynamische Nachladen. Damit wird die Collection dann befüllt und die Entities wander dann auch mit auf den Client.

Gruß
Ollie
 
Danke Oliver,

Ok. Ich werde doch um die DTOs in remoting nicht herum kommen.
Ich habe da auch etwas interesantes gefunden:

http://www.kiltz.de/Wiki.jsp?page=Hibernate.Mapping.Lazy

Das klingt venünftig, aber ich habe doch meine Bedenken, wegen von dir angesprochenm Problem: "wenn sich domain objects ändern, dann schlägt es sich rauf zum Client."

Ok ich werde DTOs für client einfügen und nur die informationen Liefern, die client aktuel braucht. Meine Überlegung ist, ein bestimmtes DTOs entspricht genau z.B. eine Zeile in einer Tabelle oder einer View. Ist das gut, oder nicht so?
 
Ok ich werde DTOs für client einfügen und nur die informationen Liefern, die client aktuel braucht. Meine Überlegung ist, ein bestimmtes DTOs entspricht genau z.B. eine Zeile in einer Tabelle oder einer View. Ist das gut, oder nicht so?

Genau das tut es, das tut aber dein Domänenobjekt ja auch.

In den meisten Fällen hast du einen technologieneutralen Service, der Domänenobjekte ausspuckt. Technologieneutral in dem Sinne, dass er nicht weiß, ob er als EJB Referenz zur Verfügung gestellt wird, als WebService oder in einer Webseite. Für jede dieser potentiellen Frontends schreibt man dann im Allgemeinen Adapter, die den Service in die jeweilige technologie exportieren. D.h. sie implementieren technologiespezifische Schnittstellen, bereiten herinkommende Daten auf / vor, delegieren an den Service und bereiten zurückzugebende Daten für den Client vor.

Genau hier weist du dann auch, welche Daten der Client genau benötigt. Dementsprechend befüllst du in diesen Exportern dann auch die DTOs entsprechend der Anforderungen des Clients. Dementsprechend stehe ich diesem Preload Konzept aus deinem Link skeptisch gegenüber. Da muss im Endeffekt die Serviceschicht bzw. das DAO schon wissen, welche Daten ich brauche. Das trägt dann u.U. clientspzifisches Wissen in diese Schichten, was besonders dann zu Problemen führt, wenn du mehrere Clients hast, die unterschiedliche Sichten auf dein Domänenmodell haben.

Gruß
Ollie
 
Danke Oliver,

mittlerweile finde ich die DTOs gar nicht so übel, sogar cool. Die nehme ich jetzt aber nur für den Remote client und WedServices. Danke dir.
 
Genauso ist es gedacht. Als Faustregel kann man annehmen, dass alles was in remote VMs läuft besser mit DTOs versehen wird. Ein Webfrontend im gleichen Containter kann z.B. trotzdem das Domänenmodell direkt benutzen.

Gruß
Ollie
 

Neue Beiträge

Zurück