<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>artanis.info</title>
	<atom:link href="http://www.artanis.info/blog/feed" rel="self" type="application/rss+xml" />
	<link>http://www.artanis.info/blog</link>
	<description></description>
	<lastBuildDate>Mon, 06 Feb 2012 08:39:30 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Du weißt, daß es draußen kalt ist&#8230;</title>
		<link>http://www.artanis.info/blog/archives/1147</link>
		<comments>http://www.artanis.info/blog/archives/1147#comments</comments>
		<pubDate>Mon, 06 Feb 2012 08:39:30 +0000</pubDate>
		<dc:creator>artanis</dc:creator>
				<category><![CDATA[Erlebnisse]]></category>

		<guid isPermaLink="false">http://www.artanis.info/blog/?p=1147</guid>
		<description><![CDATA[&#8230; wenn die Nasenschleimhäute beim Einatmen gefrieren.]]></description>
			<content:encoded><![CDATA[<p>&#8230; wenn die Nasenschleimhäute beim Einatmen gefrieren.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.artanis.info/blog/archives/1147/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Preistreiberei bei Pampers-Windeln</title>
		<link>http://www.artanis.info/blog/archives/1144</link>
		<comments>http://www.artanis.info/blog/archives/1144#comments</comments>
		<pubDate>Sun, 29 Jan 2012 21:20:14 +0000</pubDate>
		<dc:creator>artanis</dc:creator>
				<category><![CDATA[Allgemeines]]></category>

		<guid isPermaLink="false">http://www.artanis.info/blog/?p=1144</guid>
		<description><![CDATA[Vor einigen Tagen gab es wieder einen der obligatorischen Gutschein-Briefe von Pampers. Darin wurden neue Verpackungsgrößen angekündigt und großspurig gelobt. Da klingelten bei mir bereits einige Alarmglocken leise vor sich hin&#8230; Der Blick auf die Gutscheine offenbarte dann schon das nächste Warnsignal: Der Wert desjenigen für Windeln wurde nämlich von vier auf drei Euro gesenkt. [...]]]></description>
			<content:encoded><![CDATA[<p>Vor einigen Tagen gab es wieder einen der obligatorischen Gutschein-Briefe von Pampers. Darin wurden neue Verpackungsgrößen angekündigt und großspurig gelobt. Da klingelten bei mir bereits einige Alarmglocken leise vor sich hin&#8230; Der Blick auf die Gutscheine offenbarte dann schon das nächste Warnsignal: Der Wert desjenigen für Windeln wurde nämlich von vier auf drei Euro gesenkt.<br />
Nun stand der nächste Einkauf an und meine schlimmsten Befürchtungen wurden wahr: Die Preisschraube wurde angezogen. Und das sogar ganz ordentlich. So kostete eine Folienpackung &#8220;Baby Dry&#8221; Größe 4 bei einem Inhalt von 40 Stück bisher 8,65 Euro. Das macht einen Preis von 21,6 Cent pro Windel. Die so toll angepriesene neue Packung enthält hingegen nur noch 37 Windeln. Und wo eine Zahl gesenkt wird, muß ja eine andere erhöht werden. Welche kommt da wohl in Frage? Richtig: Der Preis. Der beträgt für diese Packung jetzt wahnwitzige 9,95 Euro. Das macht 26,9 Cent pro Windel und entspricht damit einer Preiserhöhung von sage und schreibe 24 Prozent.</p>
<p>Da fehlen einem echt die Worte&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.artanis.info/blog/archives/1144/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Spaß mit Time Machine</title>
		<link>http://www.artanis.info/blog/archives/1139</link>
		<comments>http://www.artanis.info/blog/archives/1139#comments</comments>
		<pubDate>Tue, 24 Jan 2012 09:16:30 +0000</pubDate>
		<dc:creator>artanis</dc:creator>
				<category><![CDATA[Apple & MacOS X]]></category>

		<guid isPermaLink="false">http://www.artanis.info/blog/?p=1139</guid>
		<description><![CDATA[Im Zuge der Installation meines neuen Servers vor einiger Zeit fiel bei mir auch die Entscheidung, die Time-Machine-Backups einiger Rechner im Hause an zentraler Stelle zusammenzuführen. Was lag also näher, diese Daten auf dem Server abzulegen? Mit der Version 2.2 unterstützt auch netatalk netzwerkgebundene Backups. Und gerade für Notebooks bietet sich das geradezu an: So [...]]]></description>
			<content:encoded><![CDATA[<p>Im Zuge der Installation meines neuen Servers vor einiger Zeit fiel bei mir auch die Entscheidung, die Time-Machine-Backups einiger Rechner im Hause an zentraler Stelle zusammenzuführen. Was lag also näher, diese Daten auf dem Server abzulegen? Mit der Version 2.2 unterstützt auch <a href="http://netatalk.sourceforge.net/">netatalk</a>  netzwerkgebundene Backups. Und gerade für Notebooks bietet sich das geradezu an: So kann man darauf verzichten, jedesmal einen speziellen Ort mit einer herumstehenden externen Festplatte aufzusuchen. Stattdessen findet die Sicherung völlig transparent und automatisch über das WLAN statt. <span id="more-1139"></span></p>
<p><strong>Konfiguration von netatalk</strong><br />
Auf der Serverseite muß nach der Installation von netatalk lediglich eine nutzerbasierte Freigabe für die Time Machine erstellt werden. Hierzu könnte eine Zeile ähnlich der folgenden in die <code>AppleVolumes.default</code> eingetragen werden:</p>
<pre>
/mnt/timemachine/$u "Time Machine von $u" options:tm,upriv,usedots dbpath:/mnt/timemachine/$u
</pre>
<p>Wichtig ist an dieser Stelle die Option <code>tm</code>, wodurch die Freigabe als Time-Machine-Laufwerk gekennzeichnet wird. Der Platzhalter <code>$u</code> wird durch den Namen des angemeldeten Benutzers ersetzt.</p>
<p><strong>Konfiguration der Time Machine</strong><br />
Auf der Clientseite kann nun die Time Machine konfiguriert werden. Sollte die Freigabe nicht in der Liste der verfügbaren Laufwerke auftauchen, so muß dieses Feature zunächst am Terminal über die Eingabe des folgenden Befehls freigeschaltet werden:</p>
<pre>
defaults write com.apple.systempreferences TMShowUnsupportedNetworkVolumes 1
</pre>
<p>Danach sollte die Freigabe auftauchen und auch ausgewählt werden können.</p>
<p><strong>Hintergrund</strong><br />
Was passiert nun? Die Time Machine wird mit dem ersten Backup ein sogenanntes <em>Sparse Bundle</em> anlegen, da das Dateisystem auf der Freigabe kein HFS mit Journaling ist. Mit jedem Backup wird zunächst das Image gemountet. Nach dem Backup wirden dieses auch wieder freigegeben. Dies geschieht vollautomatisch, der Anwender muß sich um nichts kümmern.<br />
Sieht man sich nun das Sparse Bundle mal etwas genauer an, so wird man feststellen, daß es aus Bands der Größe 8 MB besteht:</p>
<pre>
ls -l jupiter.sparsebundle/bands/

total 377536844
-rw-------  1 artanis  users  8388608 Jan 20 23:48 0
-rw-------  1 artanis  users  8388608 Jan 20 23:48 1
-rw-------  1 artanis  users  8388608 Jan 18 23:14 10
-rw-------  1 artanis  users  8388608 Aug 28 13:06 1000
[...]
</pre>
<p>Nun kann man sich leicht vorstellen, was das bedeutet, wenn man genügend Daten für die Time Machine hat: Es werden tausende von Dateien in nur einem Verzeichnis abgelegt:</p>
<pre>
ls -l jupiter.sparsebundle/bands/ | wc -l
    45911
</pre>
<p>Das mag dem Otto Normalverbraucher zwar egal sein, aber auf der Serverseite bedeutet es für das Betriebssystem einen Heidenaufwand. Nicht zuletzt kann die Performance der Time Machine selbst darunter leiden. </p>
<p>Wer jedoch genug Zeit übrig hat, kann eine Konvertierung des Sparse Bundles in Betracht ziehen. So wird laut <a href="http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man1/hdiutil.1.html">Manpage von hdiutil</a> eine Band-Size von bis zu 128 MB unterstützt. Vor der Konvertierung sollten zwingend die Time Machine des betreffenden Nutzers abgeschaltet und die Freigabe mit dem Sparse Bundle gemountet werden. Mit der Eingabe des folgenden Befehls im Terminal von MacOS X kann die Konvertierung durchgeführt werden:</p>
<pre>
hdiutil convert jupiter.sparsebundle -format UDSB -tgtimagekey sparse-band-size=262144 -verbose -o _jupiter.sparsebundle
</pre>
<p>Die Dateinamen müssen natürlich entsprechend angepaßt werden, Snow Leopard benennt das Sparse Bundle gemäß des Rechnernamens, Leopard vergibt den Namen nach dem Muster <code><em>rechnername_macadresse</em>.sparsebundle</code>. Im obigen Beispiel ist es <code>jupiter.sparsebundle</code>. Die Option <code>format</code> gibt das neue Format an, wir bleiben bei einem Sparse Bundle. Die Option <code>tgtimagekey</code> gefolgt vom Schlüssel <code>sparse-band-size</code> gibt die neue Band-Size an, der Wert berechnet sich aus der Anzahl von 512-Byte-Sektoren, die beim Wachsen hinzugefügt werden sollen (512 x 512 = 262144 Sektoren = 128 MB). Die Option <code>o</code> zu guter Letzt gibt den Namen des neuen Images an.<br />
Diese Operation dauert je nach Größe des Images und verwendetem Betriebssystem mehrere Stunden.<br />
Nach Abschluß der Konvertierung müssen die Images ggf. umbenannt werden, damit die Time Machine nach dem Einschalten auch auf das richtige Image zugreift.</p>
<p>In meinem Fall hat die Konvertierung eines 360 GB großen Sparse Bundles mit Lion ca. 20 Stunden gedauert, das entspricht einem Durchsatz von ca. 5 MB/s. Snow Leopard hätte vermutlich etwas um die 72 Stunden benötigt, der Versuch schlug jedoch fehl, weil sich das verwendete Notebook zum unpassendsten Zeitpunkt in den Ruhezustand verabschiedete. Meine Empfehlung daher: Einen Desktoprechner verwenden, am besten per LAN-Kabel verbunden, dann sollte das problemlos klappen.<br />
Die Anzahl der Bands hat sich im Beispiel von über 45000 auf &#8220;nur noch&#8221; 2700 verringert, nebenbei wurden ca. 25% Speicher freigemacht. Hier die Ausgabe von hdiutil:</p>
<pre>
hdiutil: convert: processing "jupiter.sparsebundle"
[...]
Driver Descriptor Map (DDM : 0) lesen …
Apple (Apple_partition_map : 1) lesen …
disk image (Apple_HFSX : 2) lesen …
...............................................................................
Dauer: 19h 11m 21.468s
Geschwindigkeit: 4.9M Byte/s
Ersparnis: 73.0 %
DIDiskImageConvertWithDiskImage: converter returned 0
created: /Volumes/Time Machine von artanis/_jupiter.sparsebundle
hdiutil: convert: result: 0
</pre>
<p><em>Weitere Informationen:<br />
<a href="http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man1/hdiutil.1.html">hdiutil(1) Mac OS X Manual Page</a><br />
<a href="http://hints.macworld.com/article.php?story=2008050913104691&#038;query=time+capsule">10.5: Improve networked Time Machine performance &#8211; Mac OS X Hints</a><br />
</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.artanis.info/blog/archives/1139/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Reboarder-Kindersitz in Deutschland</title>
		<link>http://www.artanis.info/blog/archives/1124</link>
		<comments>http://www.artanis.info/blog/archives/1124#comments</comments>
		<pubDate>Thu, 05 Jan 2012 20:19:09 +0000</pubDate>
		<dc:creator>artanis</dc:creator>
				<category><![CDATA[Allgemeines]]></category>

		<guid isPermaLink="false">http://www.artanis.info/blog/?p=1124</guid>
		<description><![CDATA[Heute mal ein Erfahrungsbericht als Elternteil. Unser Zwerg ist mittlerweile aus ihrer Babyschale herausgewachsen und so wurde es Zeit, über einen Ersatz nachzudenken. Meine Recherchen führten sehr schnell zu dem Ergebnis, einen rückwärtsgerichteten Kindersitz auch für Kleinkinder einzusetzen. Speziell in Schweden ist dies sogar bis zu einem Alter von 4 Jahren vorgeschrieben. Hier in Deutschland [...]]]></description>
			<content:encoded><![CDATA[<p>Heute mal ein Erfahrungsbericht als Elternteil. Unser Zwerg ist mittlerweile aus ihrer Babyschale herausgewachsen und so wurde es Zeit, über einen Ersatz nachzudenken. Meine Recherchen führten sehr schnell zu dem Ergebnis, einen rückwärtsgerichteten Kindersitz auch für Kleinkinder einzusetzen. Speziell in Schweden ist dies sogar bis zu einem Alter von 4 Jahren vorgeschrieben. Hier in Deutschland hält man sich bisher zu diesem Thema zurück, der ADAC hatte im vorletzten Test die rückwärtsgerichteten Sitze sogar wegen des schwierigeren Einbaus abgewertet. Im aktuellen Test sah das schon ganz anders aus und in der Gruppe 0/1 schloß ein solcher Kindersitz sogar mit der besten Bewertung in der Sicherheit ab.<br />
In Deutschland an einen solchen rückwärtsgerichteten Kindersitz zu kommen stellte sich dann jedoch als nicht einfach heraus. Der erste Kandidat war ein Multi Tech von Britax, der in Deutschland unter der Marke Römer vertrieben wird. Dies jedoch allerhöchstens von Volvo-Händlern&#8230; Eine Nachfrage bei einigen Baby-Fachgeschäften ergab in allen Fällen nur Kopfschütteln:</p>
<p>&#8220;Ich hätte gern einen Kindersitz&#8230;&#8221;<br />
&#8220;Haben wir&#8230;&#8221;<br />
&#8220;Einen rückwärtsgerichteten&#8230;&#8221;<br />
&#8220;&#8230; nicht.&#8221;</p>
<p><img src="http://www.artanis.info/blog/wp-content/uploads/2012/01/besafe.jpg" alt="" title="BeSafe iZi Combi X3" width="335" height="500" class="alignleft size-full wp-image-1125" /></p>
<p>Über das <a href="http://www.keep-kids-harnessed.org/index/autositze/rearfacing">Portal für Kindersicherheit</a> bin ich dann auf den Kindersitz <a href="http://www.hts.no/de/products/izicombi.php">BeSafe iZi Combi X3</a> von <a href="http://www.hts.no/de/index.php">HTS</a> gestoßen und war überrascht, daß dieser in Deutschland über BabyOne bezogen werden kann. Einen Anruf später war diese Information verifiziert. Die Probe in einer Filiale vor Ort war erfolgreich und nun nach gut einer Woche ist der &#8211; aufgrund spezieller, besonderer Farbwünsche &#8211; bestellte Sitz eingetroffen.</p>
<p>Heute dann der Einbau&#8230;</p>
<p>An sich garnicht soo kompliziert und man fragt sich, warum der ADAC dort abgewertet hat. Wenn man mal davon absieht, daß man sein halbes Auto zerlegen muß&#8230; <img src='http://www.artanis.info/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /><br />
Nein im Ernst, das einzig Aufwendige war es, eine Schiene des Beifahrersitzes zu lösen, um darunter einen Befestigungsgurt durchführen zu können. Der Rest ist das übliche Festgurten und gut. Natürlich kann man so einen Sitz nicht mal eben in ein anderes Auto einbauen, aber das ist auch kaum das Ziel, denke ich.</p>
<p>Der Kindersitz hat genug Platz im Wagen, sitzt absolut fest, sogar fester als die Babyschale zuvor und die erste Fahrt darin hat unserem Zwerg hervorragend gefallen. Positiv hervorzuheben ist auch die Möglichkeit, die Neigung des Sitzes in fünf Stufen einstellen zu können: Vom aufrechten Sitzen bis hin zur Schlafposition.</p>
<p><em><br />
Weitere Informationen:<br />
<a href="http://www.carseat.se/rearfacing/rear-facing-basics/">CarSeat.se</a><br />
<a href="http://www.keep-kids-harnessed.org/index/autositze/rearfacing">keep-kids-harnessed.org</a><br />
<a href="http://www.reboard-kindersitze.at/">reboard-kindersitze.at</a><br />
<a href="http://www.hts.no/de/safety/whyrearfacing.php">BeSafe</a><br />
</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.artanis.info/blog/archives/1124/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Java: DTOs automatisiert erstellen</title>
		<link>http://www.artanis.info/blog/archives/1089</link>
		<comments>http://www.artanis.info/blog/archives/1089#comments</comments>
		<pubDate>Wed, 19 Oct 2011 18:28:13 +0000</pubDate>
		<dc:creator>artanis</dc:creator>
				<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://www.artanis.info/blog/?p=1089</guid>
		<description><![CDATA[Hin und wieder verwende ich das &#8220;antiquierte&#8221; Entwurfsmuster des Datentransferobjekts (kurz DTO), um Daten zwischen Benutzeroberfläche und Backend auszutauschen. Dieses Muster war vor einigen Jahren speziell im EJB-Umfeld verbreitet, da die dort eingesetzten Entity Beans nicht zur Oberfläche gereicht werden konnten. Also hat man die für die Anzeige notwendigen Daten in ein einfaches Java-Objekt kopiert [...]]]></description>
			<content:encoded><![CDATA[<p>Hin und wieder verwende ich das &#8220;antiquierte&#8221; Entwurfsmuster des Datentransferobjekts (kurz DTO), um Daten zwischen Benutzeroberfläche und Backend auszutauschen. Dieses Muster war vor einigen Jahren speziell im EJB-Umfeld verbreitet, da die dort eingesetzten Entity Beans nicht zur Oberfläche gereicht werden konnten. Also hat man die für die Anzeige notwendigen Daten in ein einfaches Java-Objekt kopiert und dieses zur Oberfläche geschickt. Ich benutze dieses Muster häufiger und auch aktuell wieder in einer Tapestry-Anwendung. Der Grund hierfür: Durch den Einsatz der <code>@Validate</code>-Annotation würde man die Objekte des Datenmodells mit GUI-spezifischen Annotationen vermischen. Und sowas mag ich irgendwie garnicht&#8230; <img src='http://www.artanis.info/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
Nun wird vielleicht der eine oder andere, der schon einmal DTOs eingesetzt hat, bemerkt haben, daß das Hin-und-her-Kopieren der Eigenschaften eine bisweilen nervige Arbeit sein kann. So ging es mir zumindest vor ein paar Tagen wieder. Also habe ich mir etwas überlegt, um diesen Prozeß zu vereinfachen bzw. fast vollständig zu automatisieren. Diese Idee möchte ich in diesem Artikel näher vorstellen. <span id="more-1089"></span></p>
<h3>Die Ausgangssituation</h3>
<p>Als Beispiel sei folgendes übersichtliches Domänenmodell gegeben:<br />
<img src="http://www.artanis.info/blog/wp-content/uploads/2011/10/domain.png" alt="" title="Domäne" width="427" height="162" class="aligncenter size-full wp-image-1091" /><br />
Ein Konto (Account) mit seinen Daten ist genau einem Kunden (Customer) über die Eigenschaft <code>owner</code> zugeordnet. Ein zugehöriges Set an DTOs könnte wie folgt aussehen:<br />
<img src="http://www.artanis.info/blog/wp-content/uploads/2011/10/dto.png" alt="" title="DTOs" width="427" height="198" class="aligncenter size-full wp-image-1092" /><br />
Beziehungen werden aufgelöst und für die tabellarische Anzeige aller Konten wäre es schön, den Namen des Kunden zu sehen (<code>AccountDTO#customerName</code>). Außerdem wird für die Erfassung eines Kontos nur die ID des Kunden benötigt, um die Strukturen im Backend aufzubauen (<code>AccountDTO#customerId</code>).</p>
<p>Nun würde man sich vermutlich hinsetzen und Methoden schreiben, um die Daten aus den Domänenobjekten in die zugehörigen DTOs zu kopieren.</p>
<h3>Lösungsansatz</h3>
<p>Ziel der Lösung soll es sein, mit möglichst wenig manuellem Eingreifen eine automatische Übertragung der Daten vom Quell- in das Zielobjekt zu ermöglichen. Im Java-Umfeld gibt es mit den <a href="http://commons.apache.org/beanutils/">BeanUtils</a> von Apache Commons eine Bibliothek, die den Umgang mit Java-Klassen in Bezug auf den Datentransfer vereinfacht. Diese kann man also verwenden, um praktisch mit einem Einzeiler die Daten von einem Objekt in das andere zu übertragen:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">Account orig <span style="color: #339933;">=</span> ...
<span style="color: #006633;">AccountDTO</span> dest <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> AccountDTO<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
BeanUtils.<span style="color: #006633;">copyProperties</span><span style="color: #009900;">&#40;</span>dest, orig<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Allerdings kopiert diese Methode nur die primitiven Eigenschaften gleichen Namens und steigt schlimmstenfalls bei inkompatiblen Typen aus. Außerdem löst diese Methode nicht das Problem der beiden Eigenschaften <code>Account#customerId</code> und <code>Account#customerName</code>, die ja aus einem referenzierten Objekt bezogen werden. Es sind also einige Erweiterungen notwendig, die ich durch Annotationen verfügbar mache.</p>
<p>Neben den Annotationen gibt es zudem Factory-Klasse, in der die eigentliche Funktionalität implementiert ist: Die Auswertung der Annotationen und die Übertragung der Eigenschaften gemäß der Konfiguration.</p>
<h3>Die Annotationen</h3>
<p>Folgende Annotationen habe ich eingeführt:</p>
<ul>
<li><code>@DTOAttribute</code> für die genauere Angabe des Quellwertes</li>
<li><code>@DTOIgnore</code>, um eine Eigenschaft zu ignorieren</li>
<li><code>@DTOConverter</code> für die Konvertierung eines Wertes zwischen Quelle und Ziel</li>
<li><code>@DTO</code> für die optionale Validierung von Datentypen</li>
</ul>
<h4>@DTOAttribute</h4>
<p>Um die Quelle einer Eigenschaft genauer bestimmen zu können, kann die Annotation <code>@DTOAttribute</code> verwendet werden:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">@Target<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>ElementType.<span style="color: #006633;">FIELD</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
@Retention<span style="color: #009900;">&#40;</span>RetentionPolicy.<span style="color: #006633;">RUNTIME</span><span style="color: #009900;">&#41;</span>
@Documented
<span style="color: #000000; font-weight: bold;">public</span> @<span style="color: #000000; font-weight: bold;">interface</span> DTOAttribute <span style="color: #009900;">&#123;</span>
    <span style="color: #003399;">String</span> source<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Der Schlüssel <code>source</code> gibt an, woher ein Wert bezogen werden soll. Hier kann man nun mit Punktnotation auch über Eigenschaften navigieren. Hier ist im Prinzip alles erlaubt, was die BeanUtils verarbeiten können. Wichtig für die spätere Verarbeitung ist die Retention, die auf RUNTIME eingestellt werden sollte, damit die Annotation für die JVM zur Laufzeit sichtbar ist.</p>
<h4>@DTOIgnore</h4>
<p>Durch die Marker-Annotation <code>@DTOIgnore</code> kann man eine Eigenschaft im DTO von der Befüllung aus einer gleichnamigen Eigenschaft im Quellobjekt ausschließen.</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">@Target<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>ElementType.<span style="color: #006633;">FIELD</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
@Retention<span style="color: #009900;">&#40;</span>RetentionPolicy.<span style="color: #006633;">RUNTIME</span><span style="color: #009900;">&#41;</span>
@Documented
<span style="color: #000000; font-weight: bold;">public</span> @<span style="color: #000000; font-weight: bold;">interface</span> DTOIgnore <span style="color: #009900;">&#123;</span> <span style="color: #009900;">&#125;</span></pre></div></div>

<h4>@DTOConverter</h4>
<p>Die Annotation <code>@DTOConverter</code> löst das Problem der inkompatiblen Eigenschaften durch Angabe eines Konverters über den Schlüssel <code>converter</code>.</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">@Target<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>ElementType.<span style="color: #006633;">FIELD</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
@Retention<span style="color: #009900;">&#40;</span>RetentionPolicy.<span style="color: #006633;">RUNTIME</span><span style="color: #009900;">&#41;</span>
@Documented
<span style="color: #000000; font-weight: bold;">public</span> @<span style="color: #000000; font-weight: bold;">interface</span> DTOConverter <span style="color: #009900;">&#123;</span>
    @SuppressWarnings<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;rawtypes&quot;</span><span style="color: #009900;">&#41;</span>
    Class<span style="color: #339933;">&lt;?</span> <span style="color: #000000; font-weight: bold;">extends</span> DTOAttributeConverter<span style="color: #339933;">&gt;</span> converter<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Der Konverter muß die Schnittstelle <code>DTOAttributeConverter</code> implementieren. Diese Schnittstelle stellt eine Methode <code>convert()</code> zur Verfügung, mit der die Eigenschaft aus dem Quellobjekt in die Eigenschaft im Zielobjekt konvertiert wird. Die Schnittstelle ist generisch, angegeben werden jeweils der Eigenschaften-Typ in der Quelle (<code>S</code>) und im Ziel (<code>D</code>).</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">interface</span> DTOAttributeConverter<span style="color: #339933;">&lt;</span>S, D<span style="color: #339933;">&gt;</span> <span style="color: #009900;">&#123;</span>
    D convert<span style="color: #009900;">&#40;</span>S src<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<h4>@DTO</h4>
<p>Diese Annotation dient in erster Linie der Validierung der verwendeten Objekte. Sie ermöglicht eine Prüfung, ob das angegebene DTO für ein Quellobjekt als gültiges Ziel akzeptiert wird. So kann man zur Entwicklungszeit sicherstellen, daß die korrekten Paarungen aus Domänenobjekt und DTO an die Factory-Methode übergeben werden.</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">@Target<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>ElementType.<span style="color: #006633;">TYPE</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
@Retention<span style="color: #009900;">&#40;</span>RetentionPolicy.<span style="color: #006633;">RUNTIME</span><span style="color: #009900;">&#41;</span>
@Documented
<span style="color: #000000; font-weight: bold;">public</span> @<span style="color: #000000; font-weight: bold;">interface</span> DTO <span style="color: #009900;">&#123;</span>
    Class<span style="color: #339933;">&lt;?&gt;</span> target<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<h3>Die Factory-Klasse</h3>
<p>Als Basis für die Übertragung der Eigenschaften dient die oben gezeigte Methode. Ein Blick in die Quellen der BeanUtils zeigt, daß nach Ermittlung aller Eigenschaften diese nach und nach in das Ziel kopiert werden. Ich mache mir dieses Vorgehen an dieser Stelle nicht nur zu eigen, sondern erweitere es zudem um die Verarbeitung der eingeführten Annotationen. Diese Operation lagere ich in eine Klasse namens <code>DTOFactory</code> aus, die eine überladene, öffentliche Methode zur Verfügung stellt: <code>createDTO</code>. In der ersten Version erwartet die Methode zwei Instanzen, eine vom Typ des DTOs und eine vom Typ der Quelle. Die Überladung ermöglicht es, nur den Typen des DTOs sowie eine Instanz der Quelle anzugeben. Intern erzeugt diese Methode zunächst die notwendige Instanz des DTOs anhand des übergebene Typen und leitet die Verarbeitung an die erste Methode weiter.</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> DTOFactory <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #008000; font-style: italic; font-weight: bold;">/** Cache für Konverter. */</span>
    <span style="color: #000000; font-weight: bold;">private</span> HashMap<span style="color: #339933;">&lt;</span>Field, DTOAttributeConverter<span style="color: #339933;">&lt;</span>Object, Object<span style="color: #339933;">&gt;&gt;</span> converters <span style="color: #339933;">=</span>
            <span style="color: #000000; font-weight: bold;">new</span> HashMap<span style="color: #339933;">&lt;</span>Field, DTOAttributeConverter<span style="color: #339933;">&lt;</span>Object, Object<span style="color: #339933;">&gt;&gt;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #339933;">&lt;</span>T<span style="color: #339933;">&gt;</span> T createDTO<span style="color: #009900;">&#40;</span>Class<span style="color: #339933;">&lt;</span>T<span style="color: #339933;">&gt;</span> dtoClass, <span style="color: #003399;">Object</span> source<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span>
            T dto <span style="color: #339933;">=</span> dtoClass.<span style="color: #006633;">newInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            createDTO<span style="color: #009900;">&#40;</span>dto, source<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #000000; font-weight: bold;">return</span> dto<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">IllegalArgumentException</span> iae<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000000; font-weight: bold;">throw</span> iae<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">Exception</span> e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #339933;">&lt;</span>T<span style="color: #339933;">&gt;</span> <span style="color: #000066; font-weight: bold;">void</span> createDTO<span style="color: #009900;">&#40;</span>T dto, <span style="color: #003399;">Object</span> source<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// Schritt 1: Parameterprüfung</span>
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>dto <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000000; font-weight: bold;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">IllegalArgumentException</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Target object may not be null.&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>source <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000000; font-weight: bold;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">IllegalArgumentException</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Source object may not be null.&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// Schritt 2: Annotation @DTO</span>
        DTO aDto <span style="color: #339933;">=</span> dto.<span style="color: #006633;">getClass</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">getAnnotation</span><span style="color: #009900;">&#40;</span>DTO.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>aDto <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #339933;">!</span>aDto.<span style="color: #006633;">target</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">equals</span><span style="color: #009900;">&#40;</span>source.<span style="color: #006633;">getClass</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000000; font-weight: bold;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">IllegalArgumentException</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Source type '&quot;</span> <span style="color: #339933;">+</span>
                    aDto.<span style="color: #006633;">target</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">getName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #0000ff;">&quot;' expected, but found '&quot;</span> <span style="color: #339933;">+</span>
                    source.<span style="color: #006633;">getClass</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">getName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">+</span> <span style="color: #0000ff;">&quot;'.&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// Schritt 3: Eigenschaften ermitteln und verarbeiten</span>
        <span style="color: #003399;">PropertyDescriptor</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> props <span style="color: #339933;">=</span> PropertyUtils.<span style="color: #006633;">getPropertyDescriptors</span><span style="color: #009900;">&#40;</span>dto<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">int</span> i <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> i <span style="color: #339933;">&lt;</span> props.<span style="color: #006633;">length</span><span style="color: #339933;">;</span> i<span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #003399;">String</span> name <span style="color: #339933;">=</span> props<span style="color: #009900;">&#91;</span>i<span style="color: #009900;">&#93;</span>.<span style="color: #006633;">getName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
            <span style="color: #666666; font-style: italic;">// Schritt 3.1</span>
            <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;class&quot;</span>.<span style="color: #006633;">equals</span><span style="color: #009900;">&#40;</span>name<span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #339933;">!</span>PropertyUtils.<span style="color: #006633;">isWriteable</span><span style="color: #009900;">&#40;</span>dto, name<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #000000; font-weight: bold;">continue</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// class-Eigenschaft von Object ignorieren bzw. Ziel nicht änderbar</span>
            <span style="color: #009900;">&#125;</span>
&nbsp;
            <span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #003399;">Field</span> field <span style="color: #339933;">=</span> dto.<span style="color: #006633;">getClass</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">getDeclaredField</span><span style="color: #009900;">&#40;</span>name<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
                <span style="color: #666666; font-style: italic;">// Schritt 3.2: auf DTOIgnore prüfen und Eigenschaft ggf. überspringen</span>
                <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>field.<span style="color: #006633;">getAnnotation</span><span style="color: #009900;">&#40;</span>DTOIgnore.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                    <span style="color: #000000; font-weight: bold;">continue</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
&nbsp;
                <span style="color: #003399;">Object</span> value <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #339933;">;</span>
&nbsp;
                <span style="color: #666666; font-style: italic;">// Schritt 3.3: auf DTOAttribute-Annotation prüfen</span>
                DTOAttribute att <span style="color: #339933;">=</span> field.<span style="color: #006633;">getAnnotation</span><span style="color: #009900;">&#40;</span>DTOAttribute.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>att <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                    <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>PropertyUtils.<span style="color: #006633;">isReadable</span><span style="color: #009900;">&#40;</span>source, att.<span style="color: #006633;">source</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                        <span style="color: #666666; font-style: italic;">// Wert aus angegebener Quelle holen</span>
                        value <span style="color: #339933;">=</span> PropertyUtils.<span style="color: #006633;">getProperty</span><span style="color: #009900;">&#40;</span>source, att.<span style="color: #006633;">source</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                    <span style="color: #009900;">&#125;</span>
                <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>PropertyUtils.<span style="color: #006633;">isReadable</span><span style="color: #009900;">&#40;</span>source, name<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> <span style="color: #666666; font-style: italic;">// Standardverhalten</span>
                    <span style="color: #666666; font-style: italic;">// Quelle anhand gleichen Namens auslesen</span>
                    value <span style="color: #339933;">=</span> PropertyUtils.<span style="color: #006633;">getProperty</span><span style="color: #009900;">&#40;</span>source, name<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
&nbsp;
                <span style="color: #666666; font-style: italic;">// Schritt 3.4: wenn DTOConverter angegeben, Konvertierung durchführen</span>
                DTOConverter conv <span style="color: #339933;">=</span> field.<span style="color: #006633;">getAnnotation</span><span style="color: #009900;">&#40;</span>DTOConverter.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>conv <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                    DTOAttributeConverter<span style="color: #339933;">&lt;</span>Object, Object<span style="color: #339933;">&gt;</span> converter <span style="color: #339933;">=</span>
                            getConverter<span style="color: #009900;">&#40;</span>conv.<span style="color: #006633;">type</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>, conv.<span style="color: #006633;">name</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>, field<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                    value <span style="color: #339933;">=</span> converter.<span style="color: #006633;">convertFromSource</span><span style="color: #009900;">&#40;</span>value<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
                <span style="color: #009900;">&#125;</span>
&nbsp;
                <span style="color: #666666; font-style: italic;">// Schritt 3.5: Wert in Ziel schreiben</span>
                BeanUtils.<span style="color: #006633;">copyProperty</span><span style="color: #009900;">&#40;</span>dto, name, value<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">Exception</span> e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #666666; font-style: italic;">// ignorieren</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    @SuppressWarnings<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span> <span style="color: #0000ff;">&quot;unchecked&quot;</span>, <span style="color: #0000ff;">&quot;rawtypes&quot;</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #000000; font-weight: bold;">protected</span> DTOAttributeConverter<span style="color: #339933;">&lt;</span>Object, Object<span style="color: #339933;">&gt;</span> getConverter<span style="color: #009900;">&#40;</span>
            Class<span style="color: #339933;">&lt;?</span> <span style="color: #000000; font-weight: bold;">extends</span> DTOAttributeConverter<span style="color: #339933;">&gt;</span> type,
            <span style="color: #003399;">String</span> name, <span style="color: #003399;">Field</span> field<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Exception</span> <span style="color: #009900;">&#123;</span>
        DTOAttributeConverter<span style="color: #339933;">&lt;</span>Object, Object<span style="color: #339933;">&gt;</span> converter <span style="color: #339933;">=</span> converters.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span>field<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>converter <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            converter <span style="color: #339933;">=</span> type.<span style="color: #006633;">newInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            converters.<span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span>field, converter<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #000000; font-weight: bold;">return</span> converter<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Schauen wir uns das Vorgehen der Methode näher an. Im Schritt 1 wird zunächst geprüft, ob Quelle oder Ziel <code>null</code> sind. Dies ist untersagt, daher wird eine <code>IllegalArgumentException</code> geworfen.<br />
Im zweiten Schritt wird das Vorhandensein der Annotation <code>@DTO</code> überprüft. Ist das der Fall, so wird der darin angegebene, erwartete Typ des Quellobjekts mit dem tatsächlichen Datentypen verglichen. Stimmen beide Typen nicht überein, so wird auch an dieser Stelle eine Ausnahme ausgelöst.<br />
Anschließend werden die verfügbaren Eigenschaften mit Hilfe der BeanUtils ermittelt und verarbeitet. Hierzu wird zunächst geprüft, ob es sich um die Eigenschaft <code>class</code> handelt oder die Eigenschaft im DTO nicht veränderbar ist (Schritt 3.1). In diesem Fall wird sie einfach übersprungen. Auch im Falle der Annotation mit <code>@DTOIgnore</code> wird die betroffene Eigenschaft übersprungen (Schritt 3.2). In Schritt 3.3 wird nun der Wert aus der Quelle gelesen. Falls die Annotation <code>@DTOAttribute</code> existiert, wird der Wert aus der darin angegebenen Quelle gelesen, andernfalls aus der gleichnamigen Eigenschaft (Standardverhalten). Schritt 3.4 prüft auf die Annotation <code>@DTOConverter</code> und versucht in diesem Falle eine Konvertierung des Wertes mit Hilfe des angegebenen Konverters. Die Konverter werden nach der Erzeugung zwischengespeichert, um sie ggf. wiederverwenden zu können. Im letzten Schritt (3.5) wird dann der Wert in das Ziel geschrieben.<br />
Falls irgendwann während der Verarbeitung einer Eigenschaft ein Fehler auftritt, so wird die daraus resultierende Ausnahme verschluckt und die Eigenschaft damit übersprungen.</p>
<h3>Anwendungsbeispiel</h3>
<p>Wir wenden nun die Annotationen auf das oben angegebene Domänenmodell an, um dann die Daten aus einer Instanz der Klasse <code>Account</code> in eine Instanz des zugehörigen DTOs zu übertragen:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> AccountDTO <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">Long</span> id<span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">String</span> bic<span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">String</span> iban<span style="color: #339933;">;</span>
    @DTOAttribute<span style="color: #009900;">&#40;</span>source<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;owner.id&quot;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">Long</span> customerId<span style="color: #339933;">;</span>
    @DTOAttribute<span style="color: #009900;">&#40;</span>source<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;owner.name&quot;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">String</span> customerName<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// Getter und Setter (notwendig)</span>
<span style="color: #009900;">&#125;</span></pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// Objektnetz erzeugen</span>
Customer c <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Customer<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
c.<span style="color: #006633;">setId</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">Long</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">42</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
c.<span style="color: #006633;">setName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Max Mustermann&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
c.<span style="color: #006633;">setEmailAddress</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;max@mustermann.com&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
Account a <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Account<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
a.<span style="color: #006633;">setId</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">Long</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">21</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
a.<span style="color: #006633;">setBic</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;WELADED1KSD&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
a.<span style="color: #006633;">setIban</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;DE34567890123456&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
a.<span style="color: #006633;">setOwner</span><span style="color: #009900;">&#40;</span>c<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// das DTO erzeugen und mit Daten befüllen</span>
DTOFactory factory <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> DTOFactory<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
AccountDTO dto <span style="color: #339933;">=</span> factory.<span style="color: #006633;">createDTO</span><span style="color: #009900;">&#40;</span>AccountDTO.<span style="color: #000000; font-weight: bold;">class</span>, a<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Et voilà, ein Einzeiler ermöglicht uns nun bei korrekt annotiertem DTO-Typen eine Übertragung aller gewünschten Eigenschaften aus dem Domänenobjekt in das Ziel-DTO.</p>
<h3>Mögliche Erweiterungen</h3>
<p>Eine denkbare Erweiterung für die Konvertierung wäre die Verwendung von vordefinierten Beans bspw. in einem Spring-Umfeld. So könnte eine Eigenschaft <code>name</code> der Annotation <code>@DTOConverter</code> hinzugefügt werden, mit welcher die Bean-ID des zu verwendenden Konverters angegeben werden könnte. Gleichzeitig würde eine Ableitung der <code>DTOFactory</code> nötig, in welcher dann bei Vorhandensein eines Namens eine Auflösung aus der Spring-BeanFactory in der Methode <code>getConverter()</code> versucht werden würde.</p>
<p>Die Schnittstelle <code>DTOAttributeConverter</code> kann um eine Methode erweitert werden, die den Konverter in die Lage versetzt, auch die Richtung DTO -> Domänenobjekt mit einer Konvertierung der Daten zu bedienen. Auch in diesem Fall ist dann eine Erweiterung der Factory-Klasse notwendig.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.artanis.info/blog/archives/1089/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iOS 5 up and running</title>
		<link>http://www.artanis.info/blog/archives/1087</link>
		<comments>http://www.artanis.info/blog/archives/1087#comments</comments>
		<pubDate>Sat, 15 Oct 2011 18:26:05 +0000</pubDate>
		<dc:creator>artanis</dc:creator>
				<category><![CDATA[Allgemeines]]></category>

		<guid isPermaLink="false">http://www.artanis.info/blog/archives/1087</guid>
		<description><![CDATA[Dieses mal war ich recht schnell mit dem Einspielen der aktuellsten iOS-Version dabei. Zwar habe ich bereits gestern Abend den ersten Versuch gestartet, allerdings waren die Download-Server offenbar so sehr überlastet, daß allein der Download zwölf Stunden gedauert hätte. Also habe ich die Aktion auf heute morgen verschoben und siehe da, schon klappte der Download [...]]]></description>
			<content:encoded><![CDATA[<p>Dieses mal war ich recht schnell mit dem Einspielen der aktuellsten iOS-Version dabei. Zwar habe ich bereits gestern Abend den ersten Versuch gestartet, allerdings waren die Download-Server offenbar so sehr überlastet, daß allein der Download zwölf Stunden gedauert hätte. Also habe ich die Aktion auf heute morgen verschoben und siehe da, schon klappte der Download mit üblicher Geschwindigkeit. Da lagen die Amis wohl noch im Bett&#8230; <img src='http://www.artanis.info/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
Die Aktualisierung selbst führte iTunes interessanterweise trotz Klick auf den richtigen Button nicht als &#8220;Update&#8221;, sondern als &#8220;Wiederherstellung&#8221; durch. Das dauerte zwar entsprechend lange ( ca. eine Stunde), klappte aber ohne jegliche Probleme.<br />
Das neue iOS macht bisher einen sehr guten Eindruck auf meinem 3GS, die Geschwindigkeit würde ich als äquivalent zu 4.3 einschätzen. Ich habe auch bereits das für mich beste Feature gefunden: Für SMS gibt es nicht nur etwa viermal mehr Töne, nein, man kann sogar eigene wählen! Hallelujah! Nach zwei Jahren iPhone kann ich endlich wieder meinen SMS-Ton von anno dazumal verwenden. Unglaublich! Auswählen kann man den Ton unter <em>Einstellungen &#8211; Töne &#8211; SMS-Ton</em>. Dort gibt es neben der Rubrik &#8220;Hinweistöne&#8221; weiter unten die Rubrik &#8220;Klingeltöne&#8221;, in der sich dann neben den systeminternen Tönen auch die eigenen finden.<br />
In den nächsten Tagen werde ich mich dann mit den anderen &#8211; möglicherweise interessanteren &#8211; Features vertraut machen&#8230; <img src='http://www.artanis.info/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.artanis.info/blog/archives/1087/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Der Verschiebebahnhof</title>
		<link>http://www.artanis.info/blog/archives/1081</link>
		<comments>http://www.artanis.info/blog/archives/1081#comments</comments>
		<pubDate>Tue, 11 Oct 2011 19:47:32 +0000</pubDate>
		<dc:creator>artanis</dc:creator>
				<category><![CDATA[IT]]></category>

		<guid isPermaLink="false">http://www.artanis.info/blog/?p=1081</guid>
		<description><![CDATA[Heute beantworte ich mal die Frage, wie eigentlich die Historie aussieht, wenn man nur gefährliches Halbwissen im Umgang mit Git hat. Ich gebe zu, daß ich mit Git derzeit mehr Probleme bei der Einarbeitung habe, als seinerzeit mit CVS oder Subversion. Das liegt vermutlich an mangelnder Zeit und an für mich ungewöhnlichen Bedienung. Aber das [...]]]></description>
			<content:encoded><![CDATA[<p>Heute beantworte ich mal die Frage, wie eigentlich die Historie aussieht, wenn man nur gefährliches Halbwissen im Umgang mit Git hat. Ich gebe zu, daß ich mit Git derzeit mehr Probleme bei der Einarbeitung habe, als seinerzeit mit CVS oder Subversion. Das liegt vermutlich an mangelnder Zeit und an für mich ungewöhnlichen Bedienung. Aber das wird noch&#8230;</p>
<p>Jedenfalls fragte mich vor einigen Tagen ein Kollege, ob ich denn der &#8220;Merge-Hölle&#8221; entkommen sei, kurz nachdem ich einige Commits durchgeführt hatte. Wie er darauf kommt? Er hat sich die grafische Darstellung der Historie angesehen, die ihn irgendwie an einen Verschiebebahnhof erinnerte:</p>
<p><a href="http://www.artanis.info/blog/wp-content/uploads/2011/10/git.jpg" rel="lightbox"><img src="http://www.artanis.info/blog/wp-content/uploads/2011/10/git-128x46.jpg" alt="Verschiebebahnhof" title="Verschiebebahnhof" width="128" height="46" /></a></p>
<p>Einen sehr verrückten, möchte ich hinzufügen&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.artanis.info/blog/archives/1081/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>fr-019: poemtoahorse</title>
		<link>http://www.artanis.info/blog/archives/1073</link>
		<comments>http://www.artanis.info/blog/archives/1073#comments</comments>
		<pubDate>Sat, 01 Oct 2011 19:48:35 +0000</pubDate>
		<dc:creator>artanis</dc:creator>
				<category><![CDATA[Fundstücke]]></category>

		<guid isPermaLink="false">http://www.artanis.info/blog/?p=1073</guid>
		<description><![CDATA[Beim Durchstöbern meiner digitalen Bibliothek bin ich soeben auf Demos von Farbrausch gestoßen. Davon liegen bei mir einige seit zehn Jahren auf der Platte herum. Das waren noch Zeiten&#8230; Großartige Animationen in nur 64K gepackt. Und mein Favorit war schon immer &#8220;poemtoahorse&#8221;. Um so schlimmer ist es, daß diese Demos auf den aktuellen Windows-7-Kisten garnicht [...]]]></description>
			<content:encoded><![CDATA[<p>Beim Durchstöbern meiner digitalen Bibliothek bin ich soeben auf Demos von <a href="http://www.farbrausch.de/">Farbrausch</a> gestoßen. Davon liegen bei mir einige seit zehn Jahren auf der Platte herum. Das waren noch Zeiten&#8230; Großartige Animationen in nur 64K gepackt. Und mein Favorit war schon immer &#8220;poemtoahorse&#8221;. Um so schlimmer ist es, daß diese Demos auf den aktuellen Windows-7-Kisten garnicht mehr zu laufen scheinen. Ich habe es ohne Erfolg in einer VirtualBox ausprobiert. Die hat dabei übrigens für Mac-Absturz Numero Uno gesorgt&#8230; :S<br />
Umso besser, daß man die Demo neuerdings auch als AVI-Video <a href="http://www.farbrausch.de/prod.py?which=29">herunterladen</a> kann und es zudem eine Version auf YouTube gibt. Es kommt zwar nicht an die Qualität des Originals heran, aber trotzdem: Fröhliches Demo-Schauen&#8230;</p>
<p><iframe width="640" height="360" src="http://www.youtube.com/embed/8is4WTh4YLM?iv_load_policy=3&#038;rel=0" frameborder="0" allowfullscreen></iframe></p>
]]></content:encoded>
			<wfw:commentRss>http://www.artanis.info/blog/archives/1073/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>My Lord&#8230;</title>
		<link>http://www.artanis.info/blog/archives/1062</link>
		<comments>http://www.artanis.info/blog/archives/1062#comments</comments>
		<pubDate>Tue, 27 Sep 2011 09:27:54 +0000</pubDate>
		<dc:creator>artanis</dc:creator>
				<category><![CDATA[Fundstücke]]></category>

		<guid isPermaLink="false">http://www.artanis.info/blog/?p=1062</guid>
		<description><![CDATA[(via KeenTech)]]></description>
			<content:encoded><![CDATA[<p><iframe width="480" height="360" src="http://www.youtube.com/embed/728ABWSwPlo?iv_load_policy=3&#038;rel=0" frameborder="0" allowfullscreen></iframe></p>
<p><em>(via <a href="http://www.keentech.de/blog/2011/09/rolltreppe-im-todesstern/">KeenTech</a>)</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.artanis.info/blog/archives/1062/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Aus alt mach neu</title>
		<link>http://www.artanis.info/blog/archives/1052</link>
		<comments>http://www.artanis.info/blog/archives/1052#comments</comments>
		<pubDate>Fri, 23 Sep 2011 14:31:32 +0000</pubDate>
		<dc:creator>artanis</dc:creator>
				<category><![CDATA[IT]]></category>

		<guid isPermaLink="false">http://www.artanis.info/blog/?p=1052</guid>
		<description><![CDATA[Nach nunmehr sechs Jahren beinahe pausenlosen Einsatzes hat mein alter Server sein Rentenalter erreicht. Zeit für mich, nach einem Ersatz Umschau zu halten. Bereits Ende letzten Jahres fiel meine Entscheidung auf einen HP ProLiant MicroServer. Ich war mir nur nicht sicher, wie es mit der Hardware-Unterstützung durch FreeBSD aussah (speziell die Broadcom-Netzwerkkarte). Die Zweifel haben [...]]]></description>
			<content:encoded><![CDATA[<p>Nach nunmehr sechs Jahren beinahe pausenlosen Einsatzes hat mein alter Server sein Rentenalter erreicht. Zeit für mich, nach einem Ersatz Umschau zu halten. Bereits Ende letzten Jahres fiel meine Entscheidung auf einen <a href="http://h10010.www1.hp.com/wwpc/de/de/sm/WF05a/15351-15351-4237916-4237917-4237917-4248009.html">HP ProLiant MicroServer</a>. Ich war mir nur nicht sicher, wie es mit der Hardware-Unterstützung durch FreeBSD aussah (speziell die Broadcom-Netzwerkkarte). Die Zweifel haben sich jedoch in Luft aufgelöst und so konnte ich zuschlagen. Ich habe dem Rechner noch zusätzlichen Speicher gegönnt, werde jedoch demnächst nochmal aufrüsten müssen, so ein Apache Tomcat verschlingt ja Speicher ohne Ende&#8230; <img src='http://www.artanis.info/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Zudem habe zwei dicke Festplatten verbaut; ich bin aufgrund der schlechten Presse und der verdammten Schwebung im alten Server von Seagate zur Green-Serie von Western Digital gewechselt. Mal sehen, wie die sich so im täglichen Gebrauch machen&#8230;<br />
Mittlerweile ist auch alle notwendige Software installiert und ich habe mir geschworen, regelmäßig alle Pakete zu aktualisieren. Das habe ich auf der alten Kiste ja sträflich vernachlässigt. <img src='http://www.artanis.info/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> <span id="more-1052"></span></p>
<p><strong>Was mir gefällt</strong><br />
Der Stromverbrauch dürfte sich aufgrund des verbauten 150-Watt-Netzteils in Grenzen halten. Kein Vergleich zu dem Zeug, was man heute sonst kaufen kann, da gibt&#8217;s ja kaum noch was unter 400 Watt (Atomkraftwerk, anyone?).</p>
<p>Der Server ist cold-plug-fähig, d.h. bis zu vier Festplatten werden jeweils in einen Rahmen eingeschraubt, der dann einfach eingeschoben wird. Damit entfällt auch das Kabelgewirr.<br />
Der Rechner ist unglaublich leise, da bis auf den Gehäuselüfter keine Lüfter im Gehäuse verbaut sind. Vielmehr ist der Prozessor (Athlon Neo N36L) passiv gekühlt.</p>
<p>Die meisten Arbeiten gehen ohne Zuhilfenahme von Werkzeugen vonstatten: Festplatteneinbau (wie erwähnt), Speicherwechsel, &#8230; Und sollte dennoch einmal irgendwo eine Schraube gelöst werden müssen, dann ist das dafür notwendige Werkzeug an der Türinnenseite befestigt.</p>
<p><strong>Was mir nicht gefällt</strong><br />
Da das Gehäuse des Servers wirklich kompakt ist, gibt es starke Einschränkungen bei der Erweiterbarkeit. So muß man darauf achten, daß nur PCI-Expresskarten mit Low Profile (halbe Länge, halbe Höhe) hineinpassen. Das hat bei mir bspw. dazu geführt, daß der Sound extern in Form einer USB-Soundkarte erzeugt wird.</p>
<p><strong>Und der alte?</strong><br />
Der alte Server ist mit seiner Ablösung der letzte Rechner, den ich selbst zusammengeschraubt habe. Als Gehäuse kam ein <a href="http://www.arctic.ac/en/p/cooling/pc-case/80/silentium-t-eco-80.html?c=2184">Arctic Cooling</a> mit verändertem Design zum Einsatz, das aufgrund seiner gummigelagerten Lüfter praktisch nicht hörbar war. Diese Gummilagerungen sind allerdings auch ein Problem: Nach fünf Jahren sind die ersten porös geworden und die betroffenen Lüfter aus ihren Halterungen gefallen. So geschehen mit einem der Lüfter vor einem Jahr und mit einem weiteren vor einigen Wochen, als ich den Rechner nur mal angehoben habe.<br />
Die Seagate-Festplatten haben an sich über die Jahre ihren Dienst versehen, jedoch sind bei einer zum Schluß hin und wieder I/O-Probleme aufgetaucht, die zu Serverabstürzen geführt haben.</p>
<p><strong>Fazit</strong><br />
Wesentlicher Austauschgrund war zweifelsfrei die Hardware. Ich gebe auch dem neuen Server wohl nicht mehr als fünf Jahre. Aber ich denke, das ist ein akzeptabler Zeitraum, in dem ich hoffe, daß mir der kleine neue gute und vor allem stabile Dienste leisten wird.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.artanis.info/blog/archives/1052/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

