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.


Advertisements

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.