Archiv der Kategorie: Uncategorized

Google Guice

Ich habe mich heute mal mit Google Guice beschäftigt und das will ich hier mal kurz zusammenfassen.

Zunächst mal – Google Guice ist ein sehr leichtgewichtiges DI-Framework. Leichtgewichtig ist hier Programm.

Das Ganze ist sehr übersichtlich gestaltet und macht einen recht sympathischen Eindruck.

Ein erstes Beispiel hat man nach spätestens 5min am Laufen.

Wichtiges Infos hierzu gibt es hier

Wozu braucht man jetzt aber DI?

Die Antworten, die mir hier am wichtigsten sind sind decoupling und testability. Decoupling deswegen weil meine Anwendungsmodule (Implementierungen etc.. abhängig davon, wie die Anwendung aufgebaut ist) nicht mehr direkt voneinander abhängig sind, sondern die entsprechenden Implementierungen meiner Interfaces (IService…) von GUICE typischerweise via Constructorinjection injeziert bekommen. Genug der Theorie, direkt ein paar Codezeilen.. die Konfiguration von Guice erfolgt anders als beispielsweise in Spring nicht über externe XML-Dateien oder ähnliches sondern komplett in Java unter starker Verwendung von Annotations und Generics (sehr schön gelöst).

Eine typische Konfiguration könnte so aussehen:

public class GuiceModule implements Module {

@Override
public void configure(Binder bind) {
bind.bind(IService.class).annotatedWith(ServiceImpl2.class).to(ServiceImpl.class);
bind.bind(IService.class).to(de.md.client.impl.ServiceImpl2.class);
bind.bind(String.class).annotatedWith(Names.named(„test“)).toInstance(„MeinString“);
}

}

Das Ganze arbeitet also mit Fluent-Interfaces – sehr schön! – das Beispiel hier bindet die Implementierung ServiceImpl2 an das Interface „IService“. Wann immer in meiner Applikation also jetzt ein IService irgendwo verwendet wird, injeziert mir Guice hier ein ServiceImpl2.

Man hat auch die Möglichkeit, mehrere Implementierungen an ein Interface zu binden. Hierfür muss man als Entwickler eigene Annotations schreiben, damit Guice irgendwie mitgekommt, was wo gebraucht wird, eine einfache Annotation die für Guice vollkommen ausreichend ist, könnte so aussehen:

@Retention(RetentionPolicy.RUNTIME)
@BindingAnnotation
public @interface ServceImpl {

}

Die Annotation @BindingAnnotation kommt von Guice und zeigt an, das es sich hier tatsächlich um eine Annotation handelt, die für ein Binding definiert worden ist.

Die Verwendung ist denkbar einfach, denken wir uns einen einfache CLient aus, der folgenden Konstruktor hat.

@Inject
public Client(@ServiceImpl2 IService service, @ServceImpl IService service2) {
this.service = service;
this.service2 = service2;
}

Mit den Annotations @ServiceImpl2 und @ServiceImpl kann Guice mitgeteilt werden, welche Instanz denn jetzt wirklich injeziert werden soll – wieder sehr schön gelöst.

Weiterhin hat man die Möglichkeit, Namen zu vergeben, und Instanzen direkt an eine benannte Instanz zu injezieren.

@Inject @Named(„test“) private String s;

Schaut man sich das Module ganz oben nochmals an, sieht man, das Guice hier automatisch den String „MeinString“ injeziert. Sauber gemacht.

Auf einen ersten Blick wirkt Guice auf mich sehr sympatisch, ich werde auf jedenfall noch den einen oder anderen Blick da rein werfen, besonders intersesiert mich die Möglichkeit, Guice in Verbindung mit OSGi zu verwenden.


Vim

Zur Doku:
Der VIM-Editor kann mit Eingabe von „i“ in den Insert-Mode gesetzt werden.
Mit ESC wieder zurück
Eingabe von :q! beendet den VIM
Eingabe von :wq! beendet den VIM und speichert die Datei
dd löscht eine ganze Zeile

Automatischer Viewer Refresh

Automatischer Update eines Labelproviders

In der aktuellen Ausgabe des Eclipse-Magazins gibt es einen Artikel zum Thema Databinding,
soweit war darin für mich nicht viel neues, eines allerdings hat mich sehr gefreut, und das
wusste ich bisher nicht.

Es gibt eine Möglichkeit, einen Viewer automatisch updaten zu lassen, wenn sich eine Property im Modell ändert.
Ich hatte das bisher immer manuell (prinzipiell über ValueChangeListener) gelöst.

Was der Autor in diesem Artikel vorstellt ist der ObservableMapLabelProvider.
Dieser Labelprovider assoziiert eine Modellobjekt mit einer Property.
Als Key in der „Map“ (es ist nicht wirklich eine) wird das beobachtete Modellobjekt und zusätzlich ein PropertyDescriptor
gespeichert. Ein Aufruf von getValue() liefert das entsprechende Attribut für den Descriptor.

Der Labelprovider wird mit einer ObservableMap im Konstruktor erzeugt. Dieser registriert einen MapChangeListener
auf die Map, so dass Änderungen hierbei sofort registriert werden.

Das ganze sieht in einfachem COde für einen TableViewer ungefähr so aus:

ObservableListContentProvider cp = new ObservableListContentProvider();
viewer.setContentProvider(cp);
IObservableMap[] map = BeansObservables.observeMaps(cp
.getKnownElements(),
new String[] { „name“, „vorname“, „email“ });
viewer.setLabelProvider(new ObservableMapLabelProvider(map));
viewer.setInput((DomainUtil.getDemoData()));

Interessant hierbei ist die Zeile BeansObservables.observeMaps(cp
.getKnownElements(),
new String[] { „name“, „vorname“, „email“ });

Die Parameter hier sind eine ObservableSet von zu beobachtenden Objekten sowie die Attribute die hierbei beobachtet werden sollen.
Dies kann auch nur ein String sein statt ein String-Array.

Was hier intern passiert (man bemerke, ich arbeite mit 3.5) ist folgendes:
BeanProperties.value(propertyName).observeDetail(domain);

Was ist das jetzt?

Das ist die neue Properties-API von Galileo, dazu später mehr.

Es wird also eine Property für das zu beobachtete Attribut erzeugt, z.B. „name“ (BeanProperties.value(propertyName)),
und dieses in dem ModellObjekt überwacht (..observeDetail(domain)). Die Methode „observeDetail“ erwartet ein
ObservableSet und liefert hierfür eine Map mit den beobachteten Objekten als Keys und den entsprechenden Properties als
Values.

Woher weiß aber jetzt der Labelprovider, dass sich eine Property geändert hat?
Wenn man sich den Labelprovider anschaut passiert hier wirklich nichts anderes als das ein MapChangeListener registriert wird,
und dieser macht per se erst mal nichts anderes als das Hinzufügen und Entfernen von Elementen in einer Map zu überwachen,
was uns aber interessiert ist nicht das Hinzufügen/Entfernen, sondern dass sich ein Attribut in einem Element der Map
geändert hat, und das ist zunächst mal nicht ersichtlich, wie diese Änderung dem Labelprovider mitgeteilt wird.

Schauen wir uns das also mal genauer an:

INteressant hierbei ist die Klasse SetSimpleValueObservableMap, die die Klasse ComputedObservableMap erweitert.
Diese Klasse wird intern verwendet.

Hier findet man die Zeilen:
protected void hookListener(Object addedKey) {
if (cachedValues != null) {
cachedValues.put(addedKey, detailProperty.getValue(addedKey));
detailProperty.addListener(addedKey, listener);
}
}

DetailProperty in diesme FAll ist eine BeanValueProperty, an welche ein Listener angehängt wird, und zwar der folgende:
new ISimplePropertyListener() {
public void handlePropertyChange(
final SimplePropertyEvent event) {
if (!isDisposed() && !updating) {
getRealm().exec(new Runnable() {
public void run() {
notifyIfChanged(event.getSource());
}
});
}
}

Die Methode notifyIfChanged wiederum feuert intern ein MapChangeEvent

fireMapChange(Diffs.createMapDiffSingleChange(key, oldValue,
newValue));

Und auf diese Weise kann der Labelprovider auf Änderungen innerhalb der Bean hören.

Eclipse Link – Persistence für OSGI Teil 1 : Bundles

Hello again…

nachdem ich nun über die Feiertage etwas Zeit übrig hatte, soll hier ein weitere Post für die Verwendung von EclipseLink folgen.

Nachdem ich das alte PRojekt nun als Bundle-Zip bereitgestellt habe, und nochmals einen Blick hineingeworfen habe, ist mir aufgefallen, das die „No suitable Driver..“ SQL-Exception beim ersten Start der Anwendung erneut auftaucht, somit haben wir 2 Probleme, und zwar können wir zum Laden eines EntityManagers momentan nicht die übliche Zeile Persistence.createEntityManagerFactory(„personUnit“, map) verwenden, sondern wir umgehen die API und verwenden direkt den PersistenceProvider, den uns EclipseLink zur Verfüung stellt, und zwar indem wir statt oberer Zeile folgendes machen

EntityManagerFactory fac = new org.eclipse.persistence.jpa.osgi.PersistenceProvider().createEntityManagerFactory(
„personUnit“, map);

Leider kann ich auch den ersten Blick nicht sehen, was genau das Problem ist.

Für den weiteren Teil des Workshops habe ich das Beispiel etwas angepasst, und zwar insofern, das ich jetzt einen View eingebaut habe, der im Prinzip lediglich einen ListViewer bereitstellt, der alle Personen aus der Datenbank anzeigt. Das ganze sieht in etwa so aus:

view

Der View registriert den Viewer automatisch als SelectionProvider, der Editor registriert sich selbst als SelectionListener beim SelectionService, wodurch eine Selection im View automatisch eine Anpassung aller Attribute im Editor nach sich zieht. Man muss auch nicht extra auf „Save“ drücken, sondern da die Objekte „attached“ bleiben, werden alle Änderungen, die man im Editor macht, direkt in die Datenbank gespeichert.

Aktuell sieht man, das jedesmal, wenn die Anwendung beendet wird, alle bisher gespeicherten Daten gelöscht werden. Um das zu ändern, gleichen wir folgende Zeile an:

<property name=“eclipselink.ddl-generation“
value=“drop-and-create-tables“ />

und machen daraus:

<property name=“eclipselink.ddl-generation“
value=“
create-tables“ />

Zusätzlich müssen natürlich die Bundles für eclipselink in der TargetPlattform verfügbar sein. Ausserdem, wenn ihr die Anwendung mit der HSQL betreiben wollt, müsst ihr das entsprechende Bundle aus dem Springsource Bundle Repository runterladen. Auf dieses ist eine Dependency in der Manifest deklariert. Wollt ihr die Anwendung mit einer anderen Datenbank betreiben, müsst ihr diese Dependency entfernen und dafür sorgen, dass der Treiber zur Runtime verfügbar ist.

Die Beispielbundles in der aktuellen Version bis jetzt sind hier zum Download.

EclipseLink – Persistence für OSGI Teil 1

Für diesen Artikel hab ich mir mal das EclipseLink Projekt angeschaut, und mich darin ein bisschen eingearbeitet.

Zuerst mal eine schnelle Einführung. Was ist EclipseLink?

EclipseLink ist ein Persistenzframework für Eclipse-Applikationen und kann in verschiedensten Umgebungen arbeiten. Es bietet u.a.

  • Persistenz von Objekten über XML (JAXB)
  • Relationale Datenbanken (JPA)
  • Objektorientierte Datenbanken!
  • usw

Eine wirklich sehr gute Einführung gibts unter Link 2 (s.u)

In diesem ersten Artikel beleuchten wir mal die Installation und entwickeln eine einfache CRUD Anwendung mit Eclipse und EclipseLink.

HIerzu hol ich mir zunächst mal die benötigten Libs von hier. Das sind die OSGI-Bundles, die zum Arbeiten mit EL benötigt werden. DIes sind laut der beigelegten Readme-Datei folgende Bundles:

EclipseLink Core Functionality
——————————
– org.eclipse.persistence.core
– org.eclipse.persistence.asm
– org.eclipse.persistence.antlr
– javax.activation
– javax.jms
– javax.mail
– javax.persistence
– javax.resource
– javax.transaction
– javax.xml.rpc
– javax.xml.soap
– javax.xml.stream
– org.apache.ant

EclipseLink JPA
—————
– org.eclipse.persistence.jpa
– javax.persistence (version 1.99 required for OSGI)

EclipseLink Moxy
—————-
– org.eclipse.persistence.moxy
– javax.xml.bind

EclipseLink SDO
—————
– org.eclipse.persistence.sdo
– commonj.sdo

Schon mal eine ganze Menge. Diese entpacke ich zunächst mal in ein lokales Verzeichnis, bei mir g:developmentlibseclipse_link, und füge diese meiner TargetPlattform hinzu über

Window/Preferences/Plug-In Development / Target-Plattform/Add

target

Gruppiert man jetzt nach Location sollte man die zusätzlich geladenen Bundles erkennen:

groupes

Ok, denke ich mir eine einfache Demoanwendung aus, dann komme ich zwangsläufig wieder mal auf meine Adressverwaltung, die Personenobjekte in einer relationalen Datenbank speichert.

Hierzu sollte ein Formular angeboten werden, welches die Bearbeitung einer Person ermöglicht, das könnte etwa wie folgt aussehen (Über die Implementierung schweige ich mich hier mal aus, da dies nicht Gegenstand des Artikels sein soll).

Die einfache Implementierung unserer Person sieht so aus (man beachte den PropertyChangeSupport, der es uns erlaubt, Databinding zu verwenden).

package de.md.eclipselink.example.domain;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;

public class Person {

private String vorname;
private String nachname;
private String email;
private String telefon;
private String notiz;

private PropertyChangeSupport support;

public Person(){
this.support = new PropertyChangeSupport(this);
}

public Person(String email, String nachname, String notiz,
String telefon, String vorname) {
this();
this.email = email;
this.nachname = nachname;
this.notiz = notiz;
this.telefon = telefon;
this.vorname = vorname;

}

public String getVorname() {
return vorname;
}

public void setVorname(String vorname) {
String old = this.vorname;
this.vorname = vorname;
support.firePropertyChange(„vorname“, old, vorname);
}

public String getNachname() {
return nachname;
}

public void setNachname(String nachname) {
String old = this.telefon;
this.nachname = nachname;
support.firePropertyChange(„nachname“, old, nachname);
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
String old = this.email;
this.email = email;
support.firePropertyChange(„email“, old, email);
}

public String getTelefon() {
return telefon;
}

public void setTelefon(String telefon) {
String old = this.telefon;
this.telefon = telefon;
support.firePropertyChange(„telefon“, old, telefon);
}

public String getNotiz() {
return notiz;
}

public void setNotiz(String notiz) {
String old = this.notiz;
this.notiz = notiz;
support.firePropertyChange(„notiz“, old, notiz);
}

public void addPropertyChangeListener(PropertyChangeListener listener) {
this.support.addPropertyChangeListener(listener);
}

public void removePropertyChangeListener(PropertyChangeListener listener) {
this.support.removePropertyChangeListener(listener);
}

}
Weiterhin definieren wir einen Editor nebst EditorInput und 3 Commands mit Handlern für BEarbeiten, Laden und Speichern.

Die Laden und Speichern-Commands packen wir direkt zum Editor über eine Menü-Contribution.

<extension
point=“org.eclipse.ui.menus“>
<menuContribution
locationURI=“toolbar:de.md.eclipselink.example.editor“>
<toolbar
id=“de.md.eclipselink.example.editor.toolbar“>
<command
commandId=“de.md.eclipselink.example.save“
icon=“icons/alt_window_16.gif“
label=“speichern“
style=“push“>
</command>
<command
commandId=“de.md.eclipselink.example.load“
icon=“icons/alt_window_16.gif“
label=“laden“
style=“push“>
</command>
</toolbar>
</menuContribution>
</extension>

Die new-Command packen wir in das File-Menü:

<menuContribution
locationURI=“menu:file“>
<command
commandId=“de.md.eclipselink.example.new“
label=“Neu“
style=“push“>
</command>
</menuContribution>
</extension>

Das ganze könnte dann ungefähr so aussehen:

editor
Der Code für das Binding im Editor sieht so aus:
ctx = new DataBindingContext();
Person person = ((PersonEditorInput) getEditorInput()).getPerson();
ctx.bindValue(SWTObservables.observeText(vorname, SWT.Modify), BeansObservables
.observeValue(person, „vorname“), null, null);
ctx.bindValue(SWTObservables.observeText(nachname, SWT.Modify), BeansObservables
.observeValue(person, „nachname“), null, null);
ctx.bindValue(SWTObservables.observeText(telefon, SWT.Modify), BeansObservables
.observeValue(person, „telefon“), null, null);
ctx.bindValue(SWTObservables.observeText(email, SWT.Modify), BeansObservables
.observeValue(person, „email“), null, null);
ctx.bindValue(SWTObservables.observeText(notiz, SWT.Modify), BeansObservables
.observeValue(person, „notiz“), null, null);

Laden wir jetzt mal Probeweise eine Person bei der Instantiirung des Editors im entsprechenden Bearbeiten – Handler:
@Override
public Object execute(ExecutionEvent event) throws ExecutionException {

try {
HandlerUtil
.getActiveWorkbenchWindow(event)
.getActivePage()
.openEditor(
new PersonEditorInput(new Person(„myemail@web.de“,
„mueller“, „eine wichtige NOtiz“,
„089/123455“, „heinrich“)), PersonEditor.ID);
} catch (PartInitException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

return null;
}
sieht das ganze so aus:
editor1
Offenbar funktionierts. Nun müssen wir die Logik für das Laden und Speichern in den entsprechenden Handlern
implementieren. Hierfür implementieren wir ein DAO.
package de.md.eclipselink.example.domain;

public interface IPersonService {

public abstract Person loadPersonByName(String name);

public abstract void savePerson(Person person);

public abstract void deletePerson(Person person);

}

Nun implementieren wir die EclipseLink Unterstützung. Hierfür gibt es hier
eine entsprechende Anleitung, die uns aber primär noch nicht weiterbringt, fangen wir mal mit kleinen
Schritten an.

Zuerst müssen wir eine dependency auf das Plugin javax.persistence definieren, damit
wir Zugriff auf die entsprechenden Annotationen haben.
depend1

Danach können wir unsere Person-Bean annotieren:

Dank Lovely JPA reicht folgendes:
@Entity
public class Person {

@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE)
private Long id;

private String vorname;
private String nachname;
private String email;
private String telefon;
private String notiz;

private PropertyChangeSupport support;

public Person(){
this.support = new PropertyChangeSupport(this);
}

public Person(String email, String nachname, String notiz,
String telefon, String vorname) {
this();
this.email = email;
this.nachname = nachname;
this.notiz = notiz;
this.telefon = telefon;
this.vorname = vorname;

}

public String getVorname() {
return vorname;
}

public void setVorname(String vorname) {
String old = this.vorname;
this.vorname = vorname;
support.firePropertyChange(„vorname“, old, vorname);
}

public String getNachname() {
return nachname;
}

public void setNachname(String nachname) {
String old = this.telefon;
this.nachname = nachname;
support.firePropertyChange(„nachname“, old, nachname);
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
String old = this.email;
this.email = email;
support.firePropertyChange(„email“, old, email);
}

public String getTelefon() {
return telefon;
}

public void setTelefon(String telefon) {
String old = this.telefon;
this.telefon = telefon;
support.firePropertyChange(„telefon“, old, telefon);
}

public String getNotiz() {
return notiz;
}

public void setNotiz(String notiz) {
String old = this.notiz;
this.notiz = notiz;
support.firePropertyChange(„notiz“, old, notiz);
}

public void addPropertyChangeListener(PropertyChangeListener listener) {
this.support.addPropertyChangeListener(listener);
}

public void removePropertyChangeListener(PropertyChangeListener listener) {
this.support.removePropertyChangeListener(listener);
}

Die einfachst mögliche Implementierung des DAO ist:
public class PersonService implements IPersonService {

private EntityManager mgr;
private static PersonService INSTANCE = new PersonService();

private PersonService() {
mgr = Persistence.createEntityManagerFactory(„personUnit“)
.createEntityManager();

}

public static PersonService getInstance(){
return INSTANCE;
}

/*
* (non-Javadoc)
*
* @see
* de.md.eclipselink.example.domain.IPersonService#loadPersonByName(java
* .lang.String)
*/
public Person loadPersonByName(String name) {
return mgr.find(Person.class,name);
}

/*
* (non-Javadoc)
*
* @see
* de.md.eclipselink.example.domain.IPersonService#savePerson(de.md.eclipselink
* .example.domain.Person)
*/
public void savePerson(Person person) {
mgr.merge(person);
}

/*
* (non-Javadoc)
*
* @seede.md.eclipselink.example.domain.IPersonService#deletePerson(de.md.
* eclipselink.example.domain.Person)
*/
public void deletePerson(Person person) {
mgr.remove(person);
}
}

Einfacher gehts nicht. Für den Zugriff bieten wir eine statische „getInstance“ Methode an, SIngleton
lässt grüssen, normalerweise würde ich das nciht so machen, und jedem auf die Finger klopfen
der es probiert, aber „for the sake of demonstration, why not“, wie einmal ein kluger Mann gesagt hat.

Hierfür müssen wir noch unsere Persistence.xml definieren, diese könnte so aussehen:
<persistence>
<persistence-unit name=“examplePersistenceUnit“
transaction-type=“RESOURCE_LOCAL“>
<provider>org.eclipse.persistence.jpa.PersistenceProvider<provider/>

</persistence-unit>
</persistence>

Doch halt, das wichtigste fehlt uns ja noch, für Testzwecke brauchen wir eine Datenbank, wir verwenden hierzu
im ersten Schritt eine relationale Datenbank, und am einfachsten die HSQLDB und betreiben diese InMemory.
Hierzu erst mal das entsprechende Jar von hier runterladen und in den Classpath aufnehmen.
Da dies hier nur zu Demozwecken passieren soll, ist es auf jedenfall in ORdnung , alles in ein Plug-In
zu packen.

Um EclipseLink mit HSQL betreiben zu können, erweitern wir die Persistence.xml um folgende Einträge:

<persistence>
<persistence-unit name=“examplePersistenceUnit“
transaction-type=“RESOURCE_LOCAL“>
<provider>org.eclipse.persistence.jpa.PersistenceProvider<provider/>

<properties>
<property name=„eclipselink.target-database“ value=„HSQL“/>
<property name=„eclipselink.ddl-generation“ value=„drop-and-create-tables“/>
<property name=„eclipselink.ddl-generation.output-mode“ value=„database“/>
<property name=„eclipselink.logging.level“ value=„FINEST“/>
</properties>
</persistence-unit>
</persistence>

Damit haben können wir die HSQL ansprechen, ausserdem werden unsere Tables jedesmal neu generiert.

Starten ich aber jetzt einfach mal die Anwendung, sehe ich folgendes:
Exception Description: An attempt has been made to use PersistenceUnit [personUnit],
but no bundle is available that defines that persistence unit.

Was ist passiert? Scheinbar ist alles an Ort und Stelle…
1. persistence.xml im Ordner „META-INF“
2. Attribute korrekt gemappt (behaupte ich jetzt mal)

Trotzdem kann scheinbar die Konfiguration nicht geladen werden. Wirft man mal einen Blick in die Klasse
org.eclipse.persistence.jpa.osgi.PersistenceProvider – übrigens die Klasse, die über den
Aufruf Persistence.createEntityManagerFactory… angesprochen wird, dann sieht man das hier
nach einem Parameter der folgenden Art gesucht wird:

PersistenceUnitProperties.CLASSLOADER

Ich setzt mal voraus, das jeder der sich schon ein wenig mit der Materie auseinandergesetzt hat, darüber
Bescheid weiß, das innerhalb OSGi, jedes Bundle seinen eigenen Classloader besitzt.
Scheinbar muss hier der Classloader zum Laden der persistence.xml gesetzt werden.
Versuchen wir das doch einfach mal, da die Datei persistence.xml im einzigen Plug-In unserer Anwendung liegt,
versuchen wir einfach mal, den Classloader der PersonService-Klasse zu setzen (da dieser Classloader
dem BundleClassLoader entspricht).
(Um Zugriff auf die Konstanten zu haben, muss das entspechende Package importiert werden)

Map map = new HashMap();
map.put(PersistenceUnitProperties.CLASSLOADER, Person.class
.getClassLoader());

Gleicher Aufruf:
Caused by: javax.persistence.PersistenceException:
No Persistence provider for EntityManager named personUnit

Verdammt! Scheinbar kann die persistence.xml noch immer nicht geladen werden.
Versuchen wir direkt die Implementierung und ignorieren die API:

org.eclipse.persistence.jpa.osgi.PersistenceProvider p =
new org.eclipse.persistence.jpa.osgi.PersistenceProvider();
Map map = new HashMap();
map.put(PersistenceUnitProperties.CLASSLOADER, Person.class
.getClassLoader());
EntityManagerFactory fac = p.createEntityManagerFactory(„personUnit“,
map);
EntityManager manager = fac.createEntityManager();

Und?[EL Warning]: 2008.11.21 21:57:09.046–ServerSession(1535180)–Thread(Thread[main,6,main])–java.sql.SQLException:
No suitable driver found for jdbc:hsqldb:mem:personDb

Aha!! Scheinbar wurde der EntityManager erzeugt, und es wurde versucht, auf die HSQL-Datenbank zuzugreifen.
Klingt schonmal besser, scheinbar wurde der Treiber nicht geladen.

Ok, soweit so gut, was jetzt ein Problem sein dürfte ist, das der entsprechende JDBC-Treiber nicht geladen wurde, was aber bekannt ist, ist das seit Java6 kein manuelles Laden von JDBC-Treibern mehr nötig ist, sondern dies wird automatisch über den ConnectionManager gehandhabt.
Zur leichteren Nachvollziehbarkeit machen wir jetzt folgendes:
Statt die DB direkt in-Memory zu erzeugen speichern wir die Daten lokal auf der Festplatte. Hierfür ändern wir den ConnectionString folgendermassen ab:
jdbc:hsqldb:file:d:/myperson/person“
Scheinbar hat EclipseLink auch ein Problem, wenn PersitentEntities über Plug-Ins verteilt sind (was ich ziemlich komisch finde, da dies ja genau einer DER Knackpunkte in Bezug auf OSGi ist, und das dies eigentlich ein Grund ist, das EclipseLink überhaupt eine Daseinsberechtigung hat.
Um das zu testen, erstelle ich ein zweites Plug-In, welches nichts anderes bietet als ein package „de.md.eclipselink.domain.ext“ und hierin eine Klasse „Car“, die einer bestimmten Person zugeordnet werden kann. Hierfür bekommt die Person-Klasse ein Attribut „Car“, welches gemappt wird mit „@OneToOne“.
@OneToOne
private Car auto;
Starten wir die Anwendung und versuchen eine Person zu laden bekommen wir wie erwartet:
Caused by: javax.persistence.PersistenceException: Exception [EclipseLink-28018] (Eclipse Persistence Services – 1.0.2 (Build 20081024)): org.eclipse.persistence.exceptions.EntityManagerSetupException

Klar, wir haben Car ja noch nicht als Entity markiert. Das machen wir gleich mal in der persistence.xml
<persistence-unit name=“personUnit“ transaction-type=“RESOURCE_LOCAL“>
<provider>org.eclipse.persistence.jpa.PersistenceProvider
</provider>

<class>de.md.eclipselink.example.domain.Person
</class>
<class>de.md.eclipselink.example.domain.ext.Car</class>
<properties>
<property name=“eclipselink.target-database“ value=“HSQL“ />
<property name=“eclipselink.ddl-generation“ value=“drop-and-create-tables“ />
<property name=“eclipselink.ddl-generation.output-mode“
value=“database“ />
<property name=“eclipselink.logging.level“ value=“FINEST“ />
<property name=“eclipselink.jdbc.driver“ value=“org.hsqldb.jdbcDriver“ />
<property name=“eclipselink.jdbc.url“ value=“jdbc:hsqldb:file:d:/myperson/person“ />
<property name=“eclipselink.jdbc.user“ value=“sa“ />
<property name=“eclipselink.jdbc.password“ value=““ />
</properties>
</persistence-unit>

Starten wir jetzt die Anwendung und speichern eine Person und überprüfen hinterher die Logs der HSQl sieht man folgendes:
INSERT INTO CAR VALUES(2,’rv-md‘,’audi‘,’pkw‘)
D.h. eine Entity wurde automatisch aus einem anderen Plug-In geladen und gespeichert. Dies würde mit beispielsweise Hibernate als PersistenceProvider nicht funktionieren (Hier würde man stattdessen eine Buddy-Policy definieren um den Classpath zu erweitern).
D.h. die Gerüchte, die in den Foren umtreiben scheinen sich nicht zu bewahrheiten und EclipseLink scheint durchaus in der Lage, Entities aus beliebigen Plug-Ins zu persistieren.
Ok, bauen wir mal eine einfach e Laden funktion ein , wir definieren im package „de.md.eclipselink.example.commands“ die Klasse „LoadHandler“ mit folgendem Codefragment:
public class LoadHandler extends AbstractHandler {

@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
String name = event.getParameter(„name“);
Person person = PersonService.getInstance().loadPersonByName(name);
if (person != null) {
try {
HandlerUtil.getActiveWorkbenchWindow(event).getActivePage()
.openEditor(new PersonEditorInput(person),
PersonEditor.ID);
} catch (PartInitException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return null;
}

}
Hierfür brauchen wir ein Parametrisiertes Command.
Wie das funktioniert erkläre ich mal im schnellgang, denn zum Einen ist es heute bereits sehr spät
zum Anderen will ich darüber irgendwann einen eigenen Blogeintrag machen.

Für das Command zum Laden einer Person definieren wir folgendes:

<command

categoryId=“de.md.eclipselink.example“

id=“de.md.eclipselink.example.load“

name=“load“>

<commandParameter

id=“de.md.eclipselink.example.personName“

name=“personName“

optional=“true“>

<values

class=“de.md.eclipselink.example.commands.LoadCommandParameter“>

</values>

</commandParameter>

</command>

Wir definieren also einen Parameter für unser Command, wie aber rufe ich jetzt einen solchen Parameter auf..
Die Dokumentation hierzu ist denkbar schlecht und ich habe echt lange gebraucht, das Ding
zum LAufen zu kriegen. Im Prinzip funktioniert das ganze innerhalb des Handlers so:

public Object execute(ExecutionEvent event) throws ExecutionException {
String name = event.getParameter(„name“);
Person person = PersonService.getInstance().loadPersonByName(name);

Wie aber kommt der Name in das ExecutionEvent?
IHandlerService service = (IHandlerService) getSite()
.getService(IHandlerService.class);
ICommandService cS = (ICommandService) getSite()
.getService(ICommandService.class);
try {

Command com = cS.getCommand(„de.md.eclipselink.example.load“);
IParameter t = com.getParameter(„de.md.eclipselink.example.personName“);
Parameterization par = new Parameterization(t,“franz mueller“);
ParameterizedCommand pc = new ParameterizedCommand(com,new Parameterization[]{par});
service.executeCommand(pc, null);
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}

Links:
http://wiki.eclipse.org/Packaging_and_Deploying_EclipseLink_JPA_Applications_(ELUG)#How_to_Specify_the_Persistence_Unit_Name
http://wiki.eclipse.org/Introduction_to_EclipseLink_Application_Development_(ELUG)
http://wiki.eclipse.org/Introduction_to_Data_Access_(ELUG)#External_Connection_Pools
http://wiki.eclipse.org/Introduction_to_EclipseLink_Transactions_(ELUG)
http://wiki.eclipse.org/Introduction_to_EclipseLink_JPA_%28ELUG%29
http://wiki.eclipse.org/Using_EclipseLink_JPA_Extensions_(ELUG)
http://www.weheartcode.com/2008/08/27/eclipselink-in-j2se-rcp-applications/

http://www.jughh.org/download/attachments/1605843/EclipseLink.pdf?version=1