?? help(topic) demo() Statistische Daten- example ... · ve mit Java zu arbeiten, bieten Maven und...

4
www.javaspektrum.de 49 FACHTHEMA Wissen ist Macht Statistische Daten- verarbeitung mit Java, R und Spring Ralf Seger Statistische Datenverarbeitung ist aktuell ein hochspannendes Thema. Immer mehr Daten unterschiedlichster Art werden heute erhoben. Darun- ter große Mengen „roher“ Daten unbekannter Struktur – auch „Big Data“ genannt, die viele wertvolle Informationen für Unternehmen enthalten. Doch nur wer Strukturen und Zusammenhänge erkennt, kann mit diesem Wissen Geld verdienen. Eine Möglichkeit, diesen Schatz zu heben, bietet die statistische Analyse. Einen erweiterbaren Werkzeugkasten, bestehend aus Programmiersprache, Graphikwerkzeugen und vielem mehr, liefert R. Getting started E Viele große Anbieter wie Oracle oder SAP nutzen heute schon die von Venables und Ripley iniziierte Open-Source- Variante R der Statistiksprache S, um Data Mining zu betrei- ben. Für R existieren Tausende Pakete mit einem sehr breiten Spektrum an statistischen Funktionen wie die graphische und teilweise interaktive Darstellung von Daten, die Anbindung an Datenquellen oder andere Systeme, Tests, neuronale Netze, er- weiterbare Sprache und viele mehr. Um dem Java-Entwickler R ein weniger näherzubringen, möchte ich zunächst beschreiben, wie R seine Daten intern ver- waltet, und die wichtige Bibliothek Rserve vorstellen, von der aus R in Java verwendet werden kann. Mit Maven, Spring und der J.O.R.I.S.-Bibliothek ist eine Verbindung zu R rasch herge- stellt (s. Abb. 1). Danach folgen einige Anwendungsbeispiele und ein kleiner Ausflug in die statistische Datenanalyse. Die Installationsanleitung und Links zu Downloads sind auf der R-Projekt-Homepage [R] zu finden. Dort gibt es auch eine Anleitung zum Selberbauen. Nach dem Starten von R (Rgui.exe oder R in Linux) erscheint eine einfache, aber funktionale Kom- mandozeilenumgebung. In dieser Umgebung kann man neue Pakete installieren. Bemerkenswert ist der Kontext, in dem die- se Umgebung abläuft. R nennt diese Umgebung „Workspace“. In diesem Workspace werden Pakete geladen und alle Arten von Objekten erzeugt und verarbeitet. Eine Vielzahl an Online-Ressourcen wie Handbücher und Blogs helfen beim Einstieg. Die riesige Menge an Paketen wirkt zwar zunächst abschreckend, in der Praxis kommt man aber mit wenigen Paketen und mit der Basis schon recht weit. Hilfe gibt es über die Kommandos ?, ??, help(topic), demo() und example(..). Um mit Java und R zu starten, benötigen wir jetzt noch die Bibliothek Rserve. Fast alle Bibliotheken lassen sich in Rgui/R über install.packages installieren. Also noch install. packages("Rserve") in der R-Shell eingeben, eine Downloadquelle auswählen und der Nutzung von R aus Java heraus steht nichts mehr im Weg! Maven-Konfiguration und Verbindung mit Spring über J.O.R.I.S. Einen schnellen Weg, um nach der Installation von R und Rser- ve mit Java zu arbeiten, bieten Maven und Spring: <dependency> <groupId>org.r-project.joris</groupId> <artifactId>jr-connection-mgr</artifactId> <version>1.0.2</version> </dependency> Man benötigt nur eine minimale Spring-Konfiguration, und schon hat man in Java eine Verbindung zu R: @Configuration @Import(RServiceConfiguration.class) public class SpringConfiguration { @Bean public IRConnection managedIRConnection( IRConnectionConfig configuration, @Qualifier("rStarterProcess") ProcessService<IRConnection> rStarterService){ return new IRConnectionMgrImpl().service(rStarterService).factory( new REngineConnectionFactory()).getIRConnection(configuration); } @Bean IRConnectionConfig connectionConfiguration() { return new IRConnectionConfigImpl().steps( installLibraries("RJDBC","RXKCD","tm", "wordcloud","SnowballC","RcolorBrewer","ggplot2", "RJDBC","vioplot") .concat(loadLibraries("RJDBC","RXKCD","tm", "wordcloud", "SnowballC","RcolorBrewer","MASS","ggplot2", "reshape2","RJDBC","vioplot")) ); } } Diese IRConnection bietet in die eine Richtung Zugriff auf R ana- log zum Kommandozeilentool. Damit können R-Befehle für das Laden und Installieren von Packages, Tests, Modellierung und anderem ausgeführt werden. Die obige Konfiguration lädt die Bibliotheken ein und sorgt in vernetzten Umgebungen so- gar für die Erstinstallation. Verbindungsvariationen Um R von Java aus zu steuern, hat sich die Kombination Rserve und J.O.R.I.S. bewährt. Rserve sorgt für den Datentransport und J.O.R.I.S. bietet eine einfachere Integrati- on. Für viele Anwendungsfälle genügt es, R lokal zu installieren und Rserve auf dem Standard-Port 6311 laufen zu lassen. Wenn diese Option nicht gegeben ist, bleiben die Möglichkeiten, auf einen anderen Port aus- zuweichen oder (unter Linux) die Socket- Abb. 1: Verbindung zwischen Java und R – J.O.R.I.S. dient als Interface

Transcript of ?? help(topic) demo() Statistische Daten- example ... · ve mit Java zu arbeiten, bieten Maven und...

www.javaspektrum.de 49

Fachthema

Wissen ist Macht

Statistische Daten- verarbeitung mit Java, R und SpringRalf Seger

Statistische Datenverarbeitung ist aktuell ein hochspannendes Thema. Immer mehr Daten unterschiedlichster Art werden heute erhoben. Darun-ter große Mengen „roher“ Daten unbekannter Struktur – auch „Big Data“ genannt, die viele wertvolle Informationen für Unternehmen enthalten. Doch nur wer Strukturen und Zusammenhänge erkennt, kann mit diesem Wissen Geld verdienen. Eine Möglichkeit, diesen Schatz zu heben, bietet die statistische Analyse. Einen erweiterbaren Werkzeugkasten, bestehend aus Programmiersprache, Graphikwerkzeugen und vielem mehr, liefert R.

Getting started

E Viele große Anbieter wie Oracle oder SAP nutzen heute schon die von Venables und Ripley iniziierte Open-Source-

Variante R der Statistiksprache S, um Data Mining zu betrei-ben. Für R existieren Tausende Pakete mit einem sehr breiten Spektrum an statistischen Funktionen wie die graphische und teilweise interaktive Darstellung von Daten, die Anbindung an Datenquellen oder andere Systeme, Tests, neuronale Netze, er-weiterbare Sprache und viele mehr.

Um dem Java-Entwickler R ein weniger näherzubringen, möchte ich zunächst beschreiben, wie R seine Daten intern ver-waltet, und die wichtige Bibliothek Rserve vorstellen, von der aus R in Java verwendet werden kann. Mit Maven, Spring und der J.O.R.I.S.-Bibliothek ist eine Verbindung zu R rasch herge-stellt (s. Abb. 1). Danach folgen einige Anwendungsbeispiele und ein kleiner Ausflug in die statistische Datenanalyse.

Die Installationsanleitung und Links zu Downloads sind auf der R-Projekt-Homepage [R] zu finden. Dort gibt es auch eine Anleitung zum Selberbauen. Nach dem Starten von R (Rgui.exe oder R in Linux) erscheint eine einfache, aber funktionale Kom-mandozeilenumgebung. In dieser Umgebung kann man neue Pakete installieren. Bemerkenswert ist der Kontext, in dem die-se Umgebung abläuft. R nennt diese Umgebung „Workspace“. In diesem Workspace werden Pakete geladen und alle Arten von Objekten erzeugt und verarbeitet.

Eine Vielzahl an Online-Ressourcen wie Handbücher und Blogs helfen beim Einstieg. Die riesige Menge an Paketen wirkt zwar zunächst abschreckend, in der Praxis kommt man

aber mit wenigen Paketen und mit der Basis schon recht weit. Hilfe gibt es über die Kommandos ?, ??, help(topic), demo() und example(..).

Um mit Java und R zu starten, benötigen wir jetzt noch die Bibliothek Rserve. Fast alle Bibliotheken lassen sich in Rgui/R über install.packages installieren. Also noch install.packages("Rserve") in der R-Shell eingeben, eine Downloadquelle auswählen und der Nutzung von R aus Java heraus steht nichts mehr im Weg!

Maven-Konfiguration und Verbindung mit Spring über J.O.R.I.S.

Einen schnellen Weg, um nach der Installation von R und Rser-ve mit Java zu arbeiten, bieten Maven und Spring:

<dependency>

<groupId>org.r-project.joris</groupId>

<artifactId>jr-connection-mgr</artifactId>

<version>1.0.2</version>

</dependency>

Man benötigt nur eine minimale Spring-Konfiguration, und schon hat man in Java eine Verbindung zu R:

@Configuration

@Import(RServiceConfiguration.class)

public class SpringConfiguration {

@Bean

public IRConnection managedIRConnection(

IRConnectionConfig configuration,

@Qualifier("rStarterProcess") ProcessService<IRConnection>

rStarterService){

return new IRConnectionMgrImpl().service(rStarterService).factory(

new REngineConnectionFactory()).getIRConnection(configuration);

}

@Bean

IRConnectionConfig connectionConfiguration() {

return new IRConnectionConfigImpl().steps(

installLibraries("RJDBC","RXKCD","tm",

"wordcloud","SnowballC","RcolorBrewer","ggplot2",

"RJDBC","vioplot")

.concat(loadLibraries("RJDBC","RXKCD","tm", "wordcloud",

"SnowballC","RcolorBrewer","MASS","ggplot2",

"reshape2","RJDBC","vioplot")) );

}

}

Diese IRConnection bietet in die eine Richtung Zugriff auf R ana-log zum Kommandozeilentool. Damit können R-Befehle für das Laden und Installieren von Packages, Tests, Modellierung und anderem ausgeführt werden. Die obige Konfiguration lädt die Bibliotheken ein und sorgt in vernetzten Umgebungen so-

gar für die Erstinstallation.

Verbindungsvariationen

Um R von Java aus zu steuern, hat sich die Kombination Rserve und J.O.R.I.S. bewährt. Rserve sorgt für den Datentransport und J.O.R.I.S. bietet eine einfachere Integrati-on. Für viele Anwendungsfälle genügt es, R lokal zu installieren und Rserve auf dem Standard-Port 6311 laufen zu lassen. Wenn diese Option nicht gegeben ist, bleiben die Möglichkeiten, auf einen anderen Port aus-zuweichen oder (unter Linux) die Socket-

Abb. 1: Verbindung zwischen Java und R – J.O.R.I.S. dient als Interface

JavaSPEKTRUM 1/201650

Fachthema

Schnittstelle zu verwenden. In dem Fall muss man zusätzlich noch das Artefakt org.r-project.joris:linux-socket einbinden.

Wenn ich zum Beispiel Rserve mit J.O.R.I.S. unter Socket lau-fen lassen möchte, kann ich folgende Konfiguration (Beispiel für OpenShift) verwenden:

RSERVE_SOCKET="$OPENSHIFT_DATA_DIR"socket/rserve

JORIS_host="$OPENSHIFT_INTERNAL_IP"

JORIS_port="9999"

Damit wird der Rserve auf socket/rserve gestartet, aber intern über Port 9999 getunnelt.

Daten in R importieren

Um R-Funktionen zur Modellierung oder zum Testen zu nut-zen, muss die Datenmatrix zuerst in R eingelesen werden. Mit read.table(url,...) lassen sich Daten im Text-Format einlesen. Die Formate xls, spss, csv und mtb (minitab) werden von Haus aus unterstützt:

> sample<-read.table("http://lib.stat.cmu.edu/datasets/bodyfat",

skip=117, nrows=252)

> names(sample)<- c("density","pct","age","weight","height","neck",

"chest","abdomen","hip","thigh","knee","ankle","biceps",

"forearm","wrist")

Strukturen in Daten erkennen: Beispiel Körperfett

Obiger Datensatz enthält Messwerte: Körperfett („pct“ bzw. „density“ – prozentual oder als Dichtemessung) und dreizehn weitere erklärende Merkmale. In der Statistik spricht man von erklärenden Variablen oder Merkmalen. Diese Merkmale sind miteinander teilweise sehr hoch korreliert (s. Abb. 2).

Die Fragestellung einer statistischen Analyse lautet in die-sem Fall: Wie kann ich den Zusammenhang von Körperfett-anteil und den anderen Merkmalen am besten erklären? In der Praxis werden die Daten jetzt manuell analysiert. Man entfernt Ausreißer und die Vorbedingungen zur Modellauswahl wer-den geprüft. Gehen wir davon aus, dass die Vorbedingungen für die Anpassung eines linearen Modells hier gegeben sind.

Mit R lässt sich so mit einem einfachen Kommando ein linea-res Modell anpassen. lm berechnet das Modell aus den gewähl-ten Variablen. Die weitere Analyse erfolgt mit den R-Komman-dos summary, anova und plot:

lm(formula = pct ~ height + neck + chest + abdomen + wrist +

neck:chest, data = sample)

Residuals:

Min 1Q Median 3Q Max

-9.6843 -3.2256 -0.0685 3.0142 10.1763

Coefficients:

Estimate Std. Error t value Pr(>|t|)

(Intercept) -1.334e+02 3.288e+01 -4.055 6.73e-05 ***

height -2.124e-01 8.039e-02 -2.642 0.008780 **

neck 3.147e+00 8.678e-01 3.627 0.000349 ***

chest 1.266e+00 3.225e-01 3.927 0.000112 ***

abdomen 8.739e-01 6.491e-02 13.463 < 2e-16 ***

wrist -1.371e+00 4.591e-01 -2.987 0.003099 **

neck:chest -3.529e-02 8.209e-03 -4.299 2.48e-05 ***

---

Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 4.329 on 245 degrees of freedom

Multiple R-squared: 0.7388, Adjusted R-squared: 0.7324

F-statistic: 115.5 on 6 and 245 DF, p-value: < 2.2e-16

Der Prozess der Modellfindung ist hier sehr vereinfacht. R bie-tet einen Optimierungsalgorithmus zur Merkmalsselektion. Als Referenz helfen hier die Kommandos step und stepAIC aus der MASS-Bibliothek. Obiges Modell entstand aus dem durch stepAIC optimierten Modell. Einige wenig signifikante Varia-blen wurden der Einfachheit halber entfernt. Weiterführende Vorschläge zur Modellierung finden sich bei Burnham und An-derson [BrAn02].

Was macht das statistische Modell interessant?

Im oben beschriebenen Beispiel mit dreizehn möglichen erklä-renden Merkmalen ist eine sehr große Zahl ähnlich guter Mo-delle zu finden. Das lineare Modell könnte man verbal so über-setzen: Der Körperfettanteil – auf Basis der erhobenen Daten – kann geschätzt werden durch:

-0.2*height+3.1*neck+1.3*chest+0.9*abdomen-1.4*wrist-0.03*neck*wrist-133

Der Plot in Abbildung 3 zeigt die Abweichung der Messwerte von dieser Formel.

Warum interessiert so ein Beispiel beim Einsatz von Java? Die große Anzahl ähnlich guter Mo-delle, zum Beispiel gemessen am Akaike Information Criterion, liefert keine eindeutig beste Merkmalsaus-wahl. Um die Modell-qualität weiter zu stei-gern, können mehrere Modelle kombiniert werden. In einem da-tenbankgestützten Java-Frontend lassen sich zum Beispiel En-sembles sehr gut in-teraktiv und explora-tiv bilden.

Abb. 2: Korrelation der erklärenden Merkmale Abb. 3: Residuenplot des Beispielmodells

www.javaspektrum.deJavaSPEKTRUM 1/2016 51

Fachthema

Abb. 5: Verteilung der Gehälter

R-Daten in Java verwenden

Die Objekte aus dem R Workspace können über die IRConnec-tion direkt als generische Struktur in Java verwendet werden. Die Funktion eval(..) liefert als Ergebnis ein IREXP-Objekt zu-rück, welches einen Baum an Unterobjekten enthält (s. Abb. 4).

Die Darstellung aus Abbildung 4 gewinnt man aus den kon-vertierten IREXP-Daten. Für kleine Datenmengen kann man Ergebnisse aus R in dieser Weise verwerten. Der Vollständig-keit halber sei erwähnt, dass man über die erweiterte IJava2RCon-nection auch mittels assign direkt Arrays von primitiven Typen aus Java nach R transportieren kann. Um allerdings mit grö-ßeren Datenmengen umzugehen, ist dieser Weg mühsam und wenig performant.

Weitere Möglichkeiten zum Datentransfer zwischen Java und R

Mit den Paketen RJCDB oder RODBC erhält man in R direk-ten Datenbankzugriff. Man benötigt für RJDBC lediglich ein Java-Archiv (jar) für den Datenbanktreiber. Bei Windows und RJDBC muss eine jvm.dll über der Path-Umgebungsvariab-le auffindbar sein, sonst blockiert ein Fehler den Ladevorgang der Bibliothek. RJDBC verwendet intern die rJava-Bibliothek:

> library(RJDBC)

> drv <- JDBC("oracle.jdbc.OracleDriver",

"D://tools//oraclexe//driver//ojdbc6.jar") #windows Pfadtr enner //

> conn <- dbConnect (drv, "jdbc:oracle:thin:hr/hr@localhost:1521:xe")

> res <- dbSendQuery(conn," SELECT * FROM EMPLOYEES e JOIN

DEPARTMENTS d ON e.DEPARTMENT_ID = d.DEPARTMENT_ID")

> dataFrame <- dbFetch(res);

> dbClearResult(res)

> dbDisconnect(conn); #

> vioplot(dataFrame$SALARY, col="yellow",horizontal=TRUE, names="SALARY")

Die Daten aus einer relationalen Datenbank in ein data.frame (ei-ne benamte Zeilen-Spalten-Matrix in R) zu konvertieren, ist nicht aufwendig. Damit lassen sich in R eine Vielzahl an Plots erstellen, Modelle anpassen und Tests ausführen. Man kann beispielsweise numerische Verteilungen ansprechend visu-alisieren. Die Abbildungen 5 und 6 zeigen die Daten aus der

Oracle-Tabelle in unter-schiedlichen Detaillie-rungsgraden.

In Abbildung 5 sind die SALARY-Daten noch nach DEPARTMENT_NAME aufgeteilt worden. Obige SALARY-Daten lassen sich zum Beispiel mithilfe des Shapiro-Wilk-Tests [WikiSWT] auf ihre Normalverteilung hin untersuchen:

> shapiro.test

(dataFrame$SALARY)

data: dataFrame$SALARY

W = 0.8727,

p-value = 4.546e-08

Da wir solche Rückgabe-werte auch in Java aus-werten können, lassen sich hier praktische, dy-namische Skripte erstel-len.

Es gibt noch viele wei-tere Bibliotheken, um Verbindung mit R aufzunehmen. Hier wären SSOAP (SOAP), RCurl (HTTP, FTP ...), RLucene und andere zu nennen. Die Auswahl an Bibliotheken und Verbindungsvarianten ist damit sicherlich ausreichend. Vor dem Einsatz einer bestimmten Er-weiterungsbibliothek empfiehlt sich ein Blick in die Anleitung, um festzustellen, ob die Bibliothek schon einen entsprechen-den Reifegrad entwickelt hat.

Anwendungsbeispiel Text Mining

R bietet unter anderem auch Bibliotheken für Text Mining an, zum Beispiel tm. Die Textdaten kann man in einem Verzeichnis ablegen und mit dem tm-Package aufbereiten. Als Datenquel-

Abb. 4: Generische IREXP-Daten aus dem Beispielmodell als Java-Baum

Abb. 6: Gehälter pro Abteilung

JavaSPEKTRUM 1/201652

Fachthema

le dienen hier einige Einführungsdokumente zu R. Um eine Wordcloud zu erstellen, benötigt man die Packages tm, Snow-ballC, wordcloud und RcolorBrewer:

> texts <- Corpus (DirSource("D://Temp"))

> texts <- tm_map(texts, content_transformer(stripWhitespace))

> texts <- tm_map(texts, content_transformer(tolower))

> texts <- tm_map(texts, removeWords, stopwords("english"))

> texts <- tm_map(texts, content_transformer(stemDocument))

> wordcloud(texts, scale=c(5,0.5), max.words=100, random.order=FALSE,

rot.per=0.35, use.r.layout=FALSE, colors=brewer.pal(8, "Dark2"))

In der Praxis sammelt ein Robot diese Daten, der über ein Men-ge von Webseiten crawlt und Texte nach Lucene extrahiert.

Zusammenfassung und Ausblick

R eignet sich hervorragend, um Strukturen von Daten zu un-tersuchen. Es wurden Möglichkeiten vorgestellt, wie man Da-ten zwischen R und Java austauscht. Eine kleine Auswahl an R-Features wurde an kurzen Beispielen gezeigt. Für einen tiefe-ren Einstieg in R findet man ausführliche Handbücher auf der Website des Projekts [R]. Wer mit einem Buch starten möch-te, dem sei das Werk der Initiatoren ans Herz gelegt [VeRi01].

Die Auswahl an GUIs ist beachtlich. Erste Auswahlkriteri-en bietet ein Blogbeitrag auf www.theusrus.de [Theus11]. Außer-dem lohnt sich je nach Einsatzzweck auch ein Blick auf Rattle, Glotaran oder Deducer [Rattle, Glotaran, Deducer].

Weiterführende Themen wie der Umgang mit Big Data fin-den sich in zahlreichen Blockbeiträgen, zum Beispiel im Cattle Crew Blog [Brok15].

Auf jeden Fall gibt es keine Ausrede mehr, sich nicht mit R auseinanderzusetzen, denn die Begründung, „man sei ja nur im Java-Kontext unterwegs“, gilt heute nicht mehr. Ich wün-sche viel Vergnügen beim Verbinden und Nutzen von R!

Literatur und Links

[BodyFat] R. W. Johnson, Dataset Archive Body Fat, Depart-ment of Mathematics & Computer Science, South Dakota

School of Mines & Technology, 2.10.1995, http://lib.stat.cmu.edu/datasets/bodyfat

[BrAn02] K. P. Burnham, D. R. Anderson, Model Selection and Multimodel Inference, 2002, Springer E-Book, §6 [Brok15] P. Brokmeier, Automated Unittesting of XQueries in Oracle OSB, 29.9.2015, https://thecattlecrew.wordpress.com/[CRAN] The Comprehensive R Archive Network, Contributed Packages, http://cran.r-project.org/web/packages/ (6622 Pakete, Stand vom 07.05.2015)[Deducer] An R Graphical User Interface for Everyone, http://www.deducer.org/

[GGobi] Data Visualization System, http://www.ggobi.org/[Glotaran] A Graphical User Interface for the R-package TIMP, http://glotaran.org/

[iPlots] Interactive Plots for R, http://cran.r-project.org/web/packages/iplots/index.html

[OpenShift] https://www.openshift.com/[OracleR] Oracle R Enterprise, http://www.oracle.com/technetwork/database/database-technologies/r/r-enterprise/overview

[R] R: The R Project for Statistical Computing, http://www.r-project.org/

[Rattle] A Graphical User Interface for Data Mining using R, http://rattle.togaware.com/

[rJava] Low-Level R to Java interface, https://www.rforge.net/rJava/[Rserve] Binary R server, https://rforge.net/Rserve/[SAPHANNAR] SAP HANA R Integration Guide, http://scn.sap.com/docs/DOC-60314

[Seg14] R. Seger, Testing R/Rserve in the Cloud, 17.2.2014, http://java-r-spring.blogspot.de/

[Theus11] M. Theus, R GUIs: Which one Fits you?, Blog, 27.3.2011, http://www.theusrus.de/blog/r-guis-which-one-fits-you/[VeRi01] W. N. Venables, B. D. Ripley, Modern Applied Statistics with S-PLUS, Springer, 2001[WikiAI] http://de.wikipedia.org/wiki/Informationskriterium#Akaikes_Informationskriterium

[WikiLR] http://de.wikipedia.org/wiki/Lineare_Regression[WikiSWT] http://de.wikipedia.org/wiki/Shapiro-Wilk-TestAbb. 7: Text Mining ermittelt Rs häufigste Worte

Dr. Ralf Seger ist promovierter Statistiker mit Spezialisierung auf explorative Datenanalyse (EDA) und Multi-Model Averaging. Bei OPITZ CONSULTING entwickelt er Architekturen und spezielle, am liebsten testgetriebene, Kundenlösungen im JEE- und Spring- Umfeld. E-Mail: [email protected]

JavaSPEKTRUM ist eine Fachpublikation des Verlags:SIGS DATACOM GmbH

Lindlaustraße 2c · 53842 TroisdorfTel.: 0 22 41/23 41-100 · Fax: 0 22 41/23 41-199

E-Mail: [email protected] · www.javaspektrum.de