<?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>Cogito Ergo Blog</title>
	<atom:link href="http://cogito-ergo-blog.de/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://cogito-ergo-blog.de/blog</link>
	<description>Technical articles related to Java, HomeCinema PCs</description>
	<lastBuildDate>Thu, 02 Feb 2012 18:47:47 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Debuggen bei der JDBC Programmierung</title>
		<link>http://cogito-ergo-blog.de/blog/2012/02/02/jdbc-programmierung-debugger/</link>
		<comments>http://cogito-ergo-blog.de/blog/2012/02/02/jdbc-programmierung-debugger/#comments</comments>
		<pubDate>Thu, 02 Feb 2012 18:47:47 +0000</pubDate>
		<dc:creator>steve40</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[jdbc]]></category>

		<guid isPermaLink="false">http://euve3303.vserver.de/stefan/blog/?p=92</guid>
		<description><![CDATA[Schon zum zweiten Mal in den letzten drei Monaten hat mich ein Projektauftrag wieder tief hinunter an die Datenbank-Persisitenz geführt, wo noch richtige SQL-Statements im Code zu finden sind Für eigene Projekte und insbesondere auch für das Einarbeiten in fremde &#8230; <a href="http://cogito-ergo-blog.de/blog/2012/02/02/jdbc-programmierung-debugger/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Schon zum zweiten Mal in den letzten drei Monaten hat mich ein Projektauftrag wieder tief hinunter an die Datenbank-Persisitenz geführt, wo noch richtige SQL-Statements im Code zu finden sind <img src='http://cogito-ergo-blog.de/blog/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>Für eigene Projekte und insbesondere auch für das Einarbeiten in fremde Projekte ist es da sehr nützlich, wenn man genau sieht, was auf der Datenbank so alles passiert.</p>
<p>Hier hilft das Tool <a href="http://code.google.com/p/log4jdbc-remix/">log4jdbc-remix</a> sehr gut weiter, weil es sowohl alle Anfragen als auch die Ergebnisse mitschreiben kann. Es lassen sich auch eigene LogFormatter integrieren und selbst der Umgang mit mehreren Datenbanken ist in der neusten Release 0.2.8 kein Problem.</p>
<p>Da ich selbst auch schon über ein paar kleinere Probleme gestolpert bin, kann ich ausserdem den guten Entwickler-Support unterstreichen: Jedesmal hat Tim, der Owner des Projekts, sehr schnell reagiert und das Problem beseitigt oder einen Patch übernommen.</p>]]></content:encoded>
			<wfw:commentRss>http://cogito-ergo-blog.de/blog/2012/02/02/jdbc-programmierung-debugger/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Energiesparlampen / LED Leuchtmittel</title>
		<link>http://cogito-ergo-blog.de/blog/2012/01/31/energiesparlampen-led-leuchtmittel/</link>
		<comments>http://cogito-ergo-blog.de/blog/2012/01/31/energiesparlampen-led-leuchtmittel/#comments</comments>
		<pubDate>Tue, 31 Jan 2012 15:20:10 +0000</pubDate>
		<dc:creator>steve40</dc:creator>
				<category><![CDATA[Allgemein]]></category>

		<guid isPermaLink="false">http://cogito-ergo-blog.de/blog/?p=10080</guid>
		<description><![CDATA[Neulich wollte ich etwas für mein Ökogewissen tun und einige der stromfressende Halogenlampen (12V GU5.3) durch LED-Leuchtmittel ersetzen. Zufällig fand ich welche von NBS angeboten mit nominellen 210 Lumen bei 3 W und der Farbe warmweiss. Das zu einem Preis &#8230; <a href="http://cogito-ergo-blog.de/blog/2012/01/31/energiesparlampen-led-leuchtmittel/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Neulich wollte ich etwas für mein Ökogewissen tun und einige der stromfressende Halogenlampen (12V GU5.3) <img class="alignright size-thumbnail wp-image-10081" title="halogen-gu53" src="http://cogito-ergo-blog.de/blog/wp-content/uploads/halogen-gu53-150x150.jpg" alt="" width="150" height="150" /> durch LED-Leuchtmittel ersetzen. Zufällig fand ich welche von NBS angeboten mit nominellen 210 Lumen bei 3 W und der Farbe warmweiss. Das zu einem Preis von unter 10 Euro was mir ein guter Preis zu sein schien.</p>
<p>Mit dem Kauf der Lampen ging allerdings der Spass erst los &#8230;<span id="more-10080"></span>Bei uns im Haus gibt es nämlich viele solcher Halogenlampen als Einbauleuchten in der Decke. Das erste, was ich feststellen mußte, war, dass die neuen LEDs die Normmasse gar nicht einhalten.</p>
<p>Was bei manchen Leuchten nicht sonderlich stört, ist bei Einbauleuchten u.U. fatal, weil die LEDs schlicht nicht reinpassen.</p>
<p>Das nächste Ärgernis ist der eigentlich erwünschte geringe Energieverbrauch! Meinst sind bei Halogenbeleuchtungen nämlich elektronische Trafos verbaut (Schaltnetzteile), die eine gewisse Mindestleistungsabnahme benötigen. Wird zuwenig Strom verbraucht, dann beginnt die Spannung zu schwanken und die Netzteile laufen gefahr mit der Zeit zerstört zu werden.</p>
<p>Eingebaute LED Leuchtmittel quittieren solche Spannungsschwankungen mit einem hässlichen Flackern, schlimmer wie jede Neonröhre. Also musste ich auch noch die Netzteile austauschen, die freilich in der Zwischendecke versteckt und nur mit erhöhtem Aufwand zu erreichen waren.</p>
<p>Bleibt noch, dass LEDs immer noch nicht dimmbar sind und auch die Lichtfarbe &#8211; auch die sogenannten Warmweissen &#8211; leider nicht mit dem angenehmen Licht einer Halogenlampe mithalten können.</p>
<p>Soviel zum Thema Ernergiesparlampen / LEDs.</p>]]></content:encoded>
			<wfw:commentRss>http://cogito-ergo-blog.de/blog/2012/01/31/energiesparlampen-led-leuchtmittel/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cassandra CQL mit JDBC-Driver</title>
		<link>http://cogito-ergo-blog.de/blog/2011/12/16/cassandra-cql-mit-jdbc-driver/</link>
		<comments>http://cogito-ergo-blog.de/blog/2011/12/16/cassandra-cql-mit-jdbc-driver/#comments</comments>
		<pubDate>Fri, 16 Dec 2011 19:11:51 +0000</pubDate>
		<dc:creator>steve40</dc:creator>
				<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://cogito-ergo-blog.de/blog/?p=10072</guid>
		<description><![CDATA[Hatte endlich mal Gelegenheit mich mit einer NoSQL Datenbank zu beschäftigen: Cassandra von Apache. Allerdings fühlte ich mich aus Anwender &#8211; in meinem Fall also Anwendungsprogrammierer &#8211; in die Steinzeit der Datenbankprogrammierung zurückversetzt: es gibt nur proprietäre Schnittstellen und die sind auch &#8230; <a href="http://cogito-ergo-blog.de/blog/2011/12/16/cassandra-cql-mit-jdbc-driver/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Hatte endlich mal Gelegenheit mich mit einer NoSQL Datenbank zu beschäftigen: Cassandra von Apache. Allerdings fühlte ich mich aus Anwender &#8211; in meinem Fall also Anwendungsprogrammierer &#8211; in die Steinzeit der Datenbankprogrammierung zurückversetzt: es gibt nur proprietäre Schnittstellen und die sind auch nicht abgekündigt (Thrift). Selbst Apache empfiehlt auf ein abstrakteres API wie zum Bespiel Hector zu setzen.</p>
<p>Leider fühlt sich auch Hector in keiner Weise so an wie man es von konventioneller Datenbank-Programmierung gewohnt ist. Das Java-API ist nach meinem Geschmack &#8220;gewöhnungsbedürftig&#8221; um es einmal diplomatisch auszudrücken.</p>
<p>Dabei gibt mit Spring-JDBC (oder neuerdings mit Spring-Data) längst gute Beispiele wie man es gut machen kann. Jetzt kann man natürlich einwenden, dass diese &#8220;alten&#8221; Ansätze für SQL-Datenbanken gemacht sind und sich daher nicht für NoSQL Lösungen eignen, aber wenn man zweimal hinsieht, dann merkt man schnell, dass das gar nicht stimmt.</p>
<p><span id="more-10072"></span>Der Unterschied bei der Sicht auf die Daten besteht meiner Meinung nach im Wesentlichen im Datenmodell, oder in der Art wie man zum Datenmodell kommt: entweder klassisch relational und normalisiert, oder Abfrage-Orientiert und de-normalisiert.</p>
<p>Wenn das Datenmodell aber steht, ließe sich mit den Daten eigentlich genauso arbeiten wie mit SQL-Datenbanken: über eine Abfrage-Sprache. Im Falle von Cassandra ist das CQL. Parallelen gibt es mit Keyspace = Database, ColumnFamily = Tabelle, und Column / Row genug. Die Einschränkungen / Erweiterungen con CQL sind eben der Datenbank geschuldet (z.B. kein Join) und stören erst mal nicht, wenn man sich für das NoSQL Modell entschieden hat.</p>
<p>Jetzt gibt es mit Cassandra-JDBC sogar einen JDBC-Treiber für Cassandra, der auch CQL über JDBC in jeder Java-Anwendung verfügbar macht. Man sollte also meinen alles Handwerkzeug in Händen zu halten, um &#8220;vernünftig&#8221; arbeiten zu können.</p>
<p>Leider ist dem im aktuellen Release 1.0.5 (Dez 2011) von Cassandra nicht so.</p>
<p>Die Umsetzung ist etwas lückenhaft, so dass praktisch bei jeder anderen Anwendung (außer &#8220;Hello World&#8221;) Probleme auftreten.</p>
<p><strong>Spalten sind nicht löschbar</strong></p>
<p>Will man eine Spalte löschen, dann wird man im normalen SQL ein UPDATE &#8230; Feldname = NULL verwenden, was aber beide Spaltenorientierten Cassandra mit CQL nicht funktioniert. Dort muss stattdessen die Spalte selbst gelöscht werden mit DELETE Column(s) FROM ColumnFamily WHERE &#8230;</p>
<p>Unnötig umständlich wie ich finde. Man ist gezwungen UPDATES auf Rows in ein UPDATE und ein DELETE Statement aufzuspalten, wenn man einen Teil der Spalten löschen will. Gerade weil Cassandra aber kein festes Schema mit beliebig vielen Spalten, die auch nicht notwendigerweise gefüllt sein müssen, unterstützt, ist dies doppelt ärgerlich.</p>
<p><strong>Selects auf NULL-Spalten funktionieren nicht</strong></p>
<p>Wie schon erwähnt wird man in einer Cassandra Persistenz sicher häufig auf Rows treffen, bei der nicht alle Spalten mit Werten belegt sind. Statt bei einer CQL Anfrage dann aber NULL, oder zumindest in der JDBC Darstellung NULL bzw. den passenden Default zu liefern, stolpert man über eine Exception. Man kann gar keine Spalten abfragen, die nicht gesetzt sind.</p>
<p><strong>Unzureichende Expression-Language</strong></p>
<p>Cassandra kennt zwar bestimmte Typen Spalten. Allerdings liefert CQL kaum ausreichen Ausdrucksmöglichkeiten mit diesen Typen umzugehen. Man kann nicht einmal einen Timestamp erzeugen, ausser den nackten Long-Wert direkt einzugeben, um nur ein Beispiel zu geben. Dies erschwert die Formulierung von Abfragen wiederum unnötig. Man hätte leicht bestehende Implementierungen von ELs adaptieren können, um halbwegs verwendbare Ausdrücke in CQL einsetzen zu können.</p>
<p><strong>PreparedStatements funktionieren nicht</strong></p>
<p>In JDBC ist es eigentlich der Normalfall PreparedStatements zu nutzen. Nicht nur weil man dem Server Gelegenheit gibt, die Anfragen zu optimieren, auch Injection wird damit wirkungsvoll verhindert. Leider unterstützt Cassandra 1.0.5 solche Anfragen bislang nicht. Der JDBC-Treiber bietet sie dennoch an.</p>
<p>Wie man in der Beschreibung und im Quellcode nachlesen kann, werden die Bindings jedoch schon auf der Clientseite aufgelöst und dann zum Server geschickt. Damit könnte man leben, wenn das wenigstens funktionieren würde. Leider ist auch hier die Implementierung fehlerhaft, sodass oft genug die Bindung schlicht falsch ist und der Server die Anfrage mit einem Fehler quittiert.</p>
<p><strong>Fazit</strong></p>
<p>Will man Cassandra einsetzen, hat man sich so an das eine oder andere zu gewöhnen (oder wieder zu gewöhnen). Und damit meine ich nicht in erster Linie die Art der Datenmodellierung. Ich jedenfalls fühlte mich in mancher Hinsicht um eine paar Jahre in die Vergangenheit zurück versetzt, als man mit Oracle noch per Oracle Call Interface (OCI) sprechen musste. Aber wenns denn Cassandra sein muss &#8230;</p>]]></content:encoded>
			<wfw:commentRss>http://cogito-ergo-blog.de/blog/2011/12/16/cassandra-cql-mit-jdbc-driver/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Serendipty auf WordPress migriert</title>
		<link>http://cogito-ergo-blog.de/blog/2011/12/02/serendipty-auf-wordpress-migriert/</link>
		<comments>http://cogito-ergo-blog.de/blog/2011/12/02/serendipty-auf-wordpress-migriert/#comments</comments>
		<pubDate>Fri, 02 Dec 2011 20:43:20 +0000</pubDate>
		<dc:creator>steve40</dc:creator>
				<category><![CDATA[Allgemein]]></category>

		<guid isPermaLink="false">http://cogito-ergo-blog.de/blog/?p=10047</guid>
		<description><![CDATA[Nach einiger Mühe ist das Blog nun endlich auf WordPress umgestellt. Das Update von Serendipity auf die neuste Version war eh überfällig, also warum nicht gleich umsteigen auf WordPress. Sieht einfach hübscher aus und kann mehr. Leider ging der Import &#8230; <a href="http://cogito-ergo-blog.de/blog/2011/12/02/serendipty-auf-wordpress-migriert/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Nach einiger Mühe ist das Blog nun endlich auf WordPress umgestellt.</p>
<p>Das Update von Serendipity auf die neuste Version war eh überfällig, also warum nicht gleich umsteigen auf WordPress. Sieht einfach hübscher aus und kann mehr.</p>
<p>Leider ging der Import der Daten nicht so einfach wie gedacht.</p>
<p>Zwar gibt es <a href="http://code.google.com/p/snowulf/source/browse/#svn/trunk/wordpress/s9y-to-wp">hier</a> von Snowulf einen Importer und noch ein Update zur 1.5 <a href="http://tellini.info/2010/10/serendipity-to-wordpress/">hier</a>. Aber zum einen muss man das Readme genau lesen und sich trauen, das SQL direkt anzuwenden auch wenn die WP Version nicht mehr stimmt, zum anderen sind dann immer noch nicht alle Inhalte mirgiert.</p>
<p>Der erste Importversuch wurde gleich mittendrin abgebrochen, weil der Nutzernamen im Import schon vergeben war und das Import-Script das nicht abfängt. Leider waren die Kategorien aber schon importiert.</p>
<p>Dann wurde die mehrsprachigen Artikel nicht übernommen. Okay das waren hier nur 4 und da konnte man das Englische manuell rüberziehen.</p>
<p>Aber es geht auch die Hierarchie der Kommentare verloren. Und die Formatierung von Quellcode geht in WP auch ganz anders (zum Glück aber besser, nur umstellen muss man trotzdem).</p>
<p>Noch eine gute Quelle ist <a href="http://wiki.nodomain.cc/projekte/blog-migration">hier</a> zu finden. Dort wird auch beschrieben was man tun muss damit die alten Permlinks wieder funktionieren. Allein die Post-IDs konstant zu halten reicht natürlich nicht, weil die Links von s9y ganz anders aussehen und sich mit den Standard-Einstellungen von WP auch nicht nachbilden lassen.</p>
<p>Leider nutzt der Autor zum Umschreiben der URL eine Konfiguration lighttpd, was bei Apache2 natürlich nicht passt. Mit etwas PHP bekommt man das aber auch in der Griff. Nur die Feed-URL sind hier jetzt noch nicht gerade gezogen, aber ich befürchte soviele Abbonnenten hab ich gar nicht <img src='http://cogito-ergo-blog.de/blog/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>Naja jetzt ist&#8217;s geschafft und vielleicht lebt dadurch das Blog wieder etwas auf.</p>]]></content:encoded>
			<wfw:commentRss>http://cogito-ergo-blog.de/blog/2011/12/02/serendipty-auf-wordpress-migriert/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Der Gott des Gemetzels</title>
		<link>http://cogito-ergo-blog.de/blog/2011/12/02/der-gott-des-gemetzels/</link>
		<comments>http://cogito-ergo-blog.de/blog/2011/12/02/der-gott-des-gemetzels/#comments</comments>
		<pubDate>Fri, 02 Dec 2011 19:48:11 +0000</pubDate>
		<dc:creator>steve40</dc:creator>
				<category><![CDATA[Movies]]></category>

		<guid isPermaLink="false">http://euve3303.vserver.de/stefan/blog/?p=10020</guid>
		<description><![CDATA[Nachdem das Blog nun endlich auf WordPress umgezogen ist, hab ich auch wieder etwas mehr Schreiblust und möchte daher einen Film empfehlen: der neue Polanski Film &#8220;Der Gott des Gemetzels&#8221;. Herrlich anzuschauen, absolute Empfehlung ein &#8220;Kammerspiel&#8221; im Kino mit tollen &#8230; <a href="http://cogito-ergo-blog.de/blog/2011/12/02/der-gott-des-gemetzels/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://cogito-ergo-blog.de/blog/wp-content/uploads/gott.jpg"><img class="size-full wp-image-10022 alignleft" title="gott" src="http://cogito-ergo-blog.de/blog/wp-content/uploads/gott.jpg" alt="" width="168" height="239" /></a>Nachdem das Blog nun endlich auf WordPress umgezogen ist, hab ich auch wieder etwas mehr Schreiblust und möchte daher einen Film empfehlen:</p>
<p>der neue Polanski Film &#8220;Der Gott des Gemetzels&#8221;. Herrlich anzuschauen, absolute Empfehlung ein &#8220;Kammerspiel&#8221; im Kino mit tollen Charakteren, einer langsamen Entwicklung hin zum kompletten &#8220;Gemetzel&#8221; wirklich sehenswert. Von <a href="http://www.constantin-film.de/kino/der-gott-des-gemetzels/">Constantin Film</a>.</p>]]></content:encoded>
			<wfw:commentRss>http://cogito-ergo-blog.de/blog/2011/12/02/der-gott-des-gemetzels/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SQL Coverage messen</title>
		<link>http://cogito-ergo-blog.de/blog/2011/11/23/sql-coverage-messen/</link>
		<comments>http://cogito-ergo-blog.de/blog/2011/11/23/sql-coverage-messen/#comments</comments>
		<pubDate>Wed, 23 Nov 2011 19:01:00 +0000</pubDate>
		<dc:creator>steve40</dc:creator>
				<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://euve3303.vserver.de/stefan/blog/?p=44</guid>
		<description><![CDATA[Seit langem bin ich mal wieder aktiv in der Implementierung einer Komponente, wenn auch erst mal nur ein Prototyp. Die Persistenz ist &#8211; nach dem neusten Trend &#8220;back to the roots&#8221; &#8211; nur noch mit dem JdbcTemplate von Spring gemacht. &#8230; <a href="http://cogito-ergo-blog.de/blog/2011/11/23/sql-coverage-messen/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Seit langem bin ich mal wieder aktiv in der Implementierung einer Komponente, wenn auch erst mal nur ein Prototyp.</p>
<p>Die Persistenz ist &#8211; nach dem neusten Trend &#8220;back to the roots&#8221; &#8211; nur noch mit dem JdbcTemplate von Spring gemacht. Da kann man wieder richtiges SQL schreiben und weiß auch genau was passiert (bei Hibernate war ich mir nicht immer so ganz sicher).</p>
<p>Als es dann ans Testen ging und ich mir Gedanken um die Testabdeckung machte, fiel mir auf, dass das was bei if-Anweisungen oder bedingter Zuweisung im Java-Code als &#8220;missed 2 of 4 branches&#8221; an gemeckert wurde, an vielen Stellen in den Where-Clauses der SQL-Statements genauso auftritt.</p>
<p>Die Coverage in Java war also bei mancher Methode auf 100% aber das SQL-Statement ließ viele Varianten von ResultSets zu je nach dem, was man für Testdaten verwendet und welche konkreten Parameter man bindet.</p>
<p>Wie also läßt sich die SQL-Coverage messen?<br />
<span id="more-43"></span></p>
<h2>SQL tracen</h2>
<p>Zunächst einmal ist es nützlich die SQL-Statement mitschrieben zu lassen, die tatsächlich ausgeführt werden inklusive der aktuell gebundenen Parameter. Hierfür kann man Tools wie <a class="moz-txt-link-freetext" href="http://code.google.com/p/log4jdbc-remix/">http://code.google.com/p/log4jdbc-remix/</a> bzw. <span class="moz-txt-link-freetext"><a href="http://code.google.com/p/log4jdbc/">http://code.google.com/p/log4jdbc/</a> verwenden. Diese JDBC-Treiber arbeiten als Proxy und werden einfach &#8220;zwischen&#8221; die Applikation und den echten Treiber &#8220;gehängt&#8221;. Dadurch wird es einfach möglich alle SQL-Statements die man bei Ablauf einer Testsuite an die Datenbank schickt mitzuschreiben.</span></p>
<p>Aber leider weiss man damit immer noch nicht, ob man nun alle möglichen &#8220;Zweige&#8221; aller Where-Bedingungen aller SQL-Statements durchlaufen hat.</p>
<h2>SQL Rules und QAShrink</h2>
<p><span class="moz-txt-link-freetext">SQL Rules und QAShrink sind zwei Tool, die genau darüber Aufschluss geben können. Sie sind in der Lage ein gegebenes SQL-Statement zu analysieren nach der &#8220;Full Predicate Coverage&#8221; Methode. Es werden also Regeln erzeugt, die alle Verzweigungen oder Varainten die ein SQL-Statement erzeugen kann, berücksichtigt.</span></p>
<p>Dabei werden nicht nur Where-Bedingungen in Betracht gezogen, sondern natürlich auch Joins oder Group By-Klauseln. SQLRules zeigt zu einen einzelnen Statement diese Rules an, so dass man sich anschauen kann, welche möglichen &#8220;Pfade&#8221; zur Ergebnisfindung durchlaufen werden können.</p>
<h2>Regeln anwenden</h2>
<p><span class="moz-txt-link-freetext">Im nächsten Schritt lassen sich diese Regeln dann gegen einen Testdatenbestand anwenden / testen. Als Ergebnis bekommt man eine Aussage, ob die betreffende Regel verwendet wurde oder nicht, also ob dieser Pfad bei den zugrunde gelegten Daten durchlaufen wurde oder nicht. Das ist genau die SQL-Coverage die man braucht.</span></p>
<p>Das andere Tool QAShrink kann dieses Prinzip gleich auf eine ganze Liste von SQL-Statements anwenden<span class="moz-txt-link-freetext">. Es erzeugt dann Aussagen bzgl. der Coverage der SQL-Statements und der Vollständigkeit bzw. der Redundanz der Testdaten.</span></p>
<p>Auf diese Weise kann man also ziemlich schnell herausfinden, welche Testdaten überflüssig und welche noch zu ergänzen sind, um &#8211; bei gegebener Liste der SQL-Statements &#8211; die SQL-Coverage möglichst hoch zu machen.</p>
<h2>Zusammenfassung</h2>
<p>Das Vorgehen zum Erreichen einer möglichst hohen SQL-Coverage läßt sich also so zusammenfassen:</p>
<ol>
<li>Mit einem JDBC-Proxy Treiber erzeugt man eine Liste von konkreten SQL-Abfragen, die von einer TestSuite mit hoher Code-Coverage erzeugt wird.</li>
<li>Die Liste der SQL-Statemant füttert man in QAShrink und läßt sie gegen den gleichen Testdatenbestand wie die TestSuite laufen.</li>
<li>Anhand der Ergebnisse kann man den Testdatenbestand so lange um Datensätze ergänzen, bis eine optimale SQL-Coverage erreicht ist.</li>
</ol>
<p>Links zu den Tools:<br />
<a class="moz-txt-link-freetext" href="http://in2test.lsi.uniovi.es/sqltools/sqlrules/">http://in2test.lsi.uniovi.es/sqltools/sqlrules/</a><br />
<a class="moz-txt-link-freetext" href="http://in2test.lsi.uniovi.es/sqltools/qashrink/">http://in2test.lsi.uniovi.es/sqltools/qashrink/</a></p>]]></content:encoded>
			<wfw:commentRss>http://cogito-ergo-blog.de/blog/2011/11/23/sql-coverage-messen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Workflow-Engine einmal anders</title>
		<link>http://cogito-ergo-blog.de/blog/2009/07/28/workflow-engine-einmal-anders/</link>
		<comments>http://cogito-ergo-blog.de/blog/2009/07/28/workflow-engine-einmal-anders/#comments</comments>
		<pubDate>Tue, 28 Jul 2009 20:52:13 +0000</pubDate>
		<dc:creator>steve40</dc:creator>
				<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://euve3303.vserver.de/stefan/blog/?p=43</guid>
		<description><![CDATA[Schon in einigen Projekten war die Herausforderung bestimmte Abläufe oder auch „Prozesse“ hochskalierbar, verlässlich ausführen zu können. Dabei kam dann von den einen Projektverantwortlichen schnell der Ruf nach einer Workflow-Engine, von den anderen eher das Gegenteil: „Bloß keine Workflow-Engine &#8230;“. &#8230; <a href="http://cogito-ergo-blog.de/blog/2009/07/28/workflow-engine-einmal-anders/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p style="margin-bottom: 0cm;">Schon in einigen Projekten war die Herausforderung bestimmte Abläufe oder auch „Prozesse“ hochskalierbar, verlässlich ausführen zu können. Dabei kam dann von den einen Projektverantwortlichen schnell der Ruf nach einer Workflow-Engine, von den anderen eher das Gegenteil: „Bloß keine Workflow-Engine &#8230;“.</p>
<p style="margin-bottom: 0cm;">Ich selbst bin auch nicht unbedingt ein Freund von „graphischer Programmierung“ oder geschwätzigem XML, was fast schon Programmiersprache sein will, aber in fast jeder<br />
Hinsicht unhandlicher ist als eine „normale“ Programmiersprache wie <a href="http://www.scala-lang.org/">Scala</a> oder Java.</p>
<p style="margin-bottom: 0cm;">Aus diesem Grund reizte mich die Idee einen alternativen Ansatz zu versuchen. Da ich, wie gerade schon erwähnt, kein Freund von „in XML programmieren“ bin, sollte die<br />
Beschreibung des „Prozesses“ &#8211; das Prozessmodell – in Java erfolgen.</p>
<p style="margin-bottom: 0cm;">Hier bietet sich das <a href="http://de.wikipedia.org/wiki/Zustand_(Entwurfsmuster)">State-Pattern</a> an, welches eine Prozessablauf mit Hilfe von Zustandsobjekten und einem Kontext beschreibt. Konkret werden also nur Interfaces bzw. abstrakte Basisklassen benötigt, die von einem konkreten Prozess implementiert<br />
werden. Dazu der „Contract“ der den Ablauf / die Semantik beschreibt und schon kann ein „Prozess“ statt in XML in Java geschrieben werden.</p>
<p><span id="more-41"></span></p>
<p style="margin-bottom: 0cm;">Allerdings kann man nun einwenden, dass das normale Ausführungsmodell einer JVM mit Threads nicht die gleichen Vorteile bietet wie eine Workflow-Engine.</p>
<p style="margin-bottom: 0cm;">Inspiriert von den Ansätzen von <a href="https://dalma.dev.java.net/nonav/maven/index.html">Dalma</a> und <a href="http://commons.apache.org/sandbox/javaflow/">Javaflow</a> oder auch den Arbeiten von Doug Lea (FJTasks) ist aber auch auf einer Java VM mehr möglich, als einfach für jeden Prozess<br />
und jede seiner Nebenläufigkeiten einen neuen Thread zu starten.</p>
<p style="margin-bottom: 0cm;">Würde man das tun, wären diese bei den eingangs genannten Anforderungen sicher bald aufgebraucht (viele Prozessinstanzen, womöglich viele davon nur wartend).</p>
<p style="margin-bottom: 0cm;">Auch mit der Skalierbarkeit haben viele Workflow-Engines gewisse Probleme, weil sich die Arbeit schlecht über einen Cluster verteilen läßt. Aber auch hier gibt es im Standard<br />
Java gute Lösungansätze, wie z.B. <a href="http://www.gridgain.com/">GridGain</a>.</p>
<p style="margin-bottom: 0cm;">Ein weiterer Aspekt, den Workflow-Engine bedienen, ist Prozesspersistenz. Prozesse, die auf der Engine ablaufen, lassen sich persistieren. Damit ist der Ablauf unterbrechbar, wiederherstellbar und nachvollziehbar. Wenn allerdings Prozesse normale durch normale Java-Objekte dargestellt werden, dann lassen sie sich auch mit einfachen ORM Mitteln persistieren.</p>
<p style="margin-bottom: 0cm;">Zu guter letzt sind die meisten Prozesse immer auf irgendwelche Services angewiesen, die von ihnen aufgerufen werden, oder Calls an die Prozesse absetzen. Hierzu soll<br />
für das Java basierende Prozessmodell ein Container /Application-Server zum Einsatz kommen. Meine Wahl fiel auf <a href="http://www.springsource.org/">Spring</a>, wobei sicher auch andere Lösungen denkbar wären.</p>
<p style="margin-bottom: 0cm;">Das Rezept für <em>meine </em>Workflow-Engine lautet also:</p>
<ul>
<li>
<p style="margin-bottom: 0cm;">Prozesse sind Java-Klassen, die nach dem State-Pattern einen Ablauf implementieren.</p>
</li>
<li>
<p style="margin-bottom: 0cm;">Diese Klassen sind typischerweise Spring-Beans, die vom Container „Services“ konsumieren.</p>
</li>
<li>
<p style="margin-bottom: 0cm;">Die Klassen sind Serializable und damit „Remoting“-fähig für GridGain.</p>
</li>
<li>
<p style="margin-bottom: 0cm;">Die Klassen tragen (optional) Persistenz-Annotationen, welche die Engine dafür nutzt den Prozesszustand zu persistieren.</p>
</li>
</ul>
<p style="margin-bottom: 0cm;">Heraus kommt eine Lösung,</p>
<ul>
<li>
<p style="margin-bottom: 0cm;">die hochskalierbar ist, weil Prozesse über GridGain auf einem Cluster von Nodes verteilt werden können.</p>
</li>
<li>
<p style="margin-bottom: 0cm;">die den gewohnten Komfort einer IOC-Umgebung genießt, bei der nach Belieben „Services“ genutzt werden können (natürlich nicht nur Webservices).</p>
</li>
<li>
<p style="margin-bottom: 0cm;">die den Prozesszustand nach jedem Prozessschritt mit Hilfe eines Persistenzproviders wie z.B. Hibernate persistiert.</p>
</li>
<li>
<p style="margin-bottom: 0cm;">die Prozesse einfach als Java-Programm beschrieben, welches mit einfachsten Mitteln und voller IDE Untersützung entworfen werden kann.</p>
</li>
</ul>
<p style="margin-bottom: 0cm;">Besonders den letzten Punkt möchte ich noch einmal unterstreichen: Man kann es gar nicht hoch genug bewerten, wie viele Vorteile sich allein dadurch ergeben, dass man in<br />
der gewohnten Umgebung arbeiten kann:</p>
<ul>
<li>
<p style="margin-bottom: 0cm;">kein Lernen einer Prozessbeschreibungssprache (in XML).</p>
</li>
<li>
<p style="margin-bottom: 0cm;">alle Möglichkeiten und Konstrukte einer Programmiersprache wie Java.</p>
</li>
<li>
<p style="margin-bottom: 0cm;">die gewohnte IDE.</p>
</li>
<li>
<p style="margin-bottom: 0cm;">simples Debuggen und Testen (noch besser zu unterstützen durch Mocks und eine spezielle Engine, die ein lokales Debuggen direkt ermöglicht).</p>
</li>
<li>
<p style="margin-bottom: 0cm;">Einfachstes Wiederverwenden von vorhandenem Code oder vorhandenen Services (meist sind keinerlei „Wrapper“ oder „Adapter“ notwendig).</p>
</li>
</ul>
<p style="margin-bottom: 0cm;">Wie die Lösung konkret aussieht, werde ich wohl heute nicht mehr zusammenschreiben, deshalb wird’s demnächst hier ne Fortsetzung geben &#8230;</p>
<p style="margin-bottom: 0cm;">
]]></content:encoded>
			<wfw:commentRss>http://cogito-ergo-blog.de/blog/2009/07/28/workflow-engine-einmal-anders/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JBoss Seam mit Mondrian OLAP</title>
		<link>http://cogito-ergo-blog.de/blog/2008/09/30/jboss-seam-mit-mondrian-olap/</link>
		<comments>http://cogito-ergo-blog.de/blog/2008/09/30/jboss-seam-mit-mondrian-olap/#comments</comments>
		<pubDate>Tue, 30 Sep 2008 21:29:19 +0000</pubDate>
		<dc:creator>steve40</dc:creator>
				<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://euve3303.vserver.de/stefan/blog/?p=40</guid>
		<description><![CDATA[Der Mondrian OLAP Server, der seit einer Weile zur Pentaho-Suite gehört, kann mit einer recht leistungsfähigen Implementierung von Data-Cubes und der MDX-Abfragesprache aufwarten. Allerdings kommt die mitgelieferte Oberfläche etwas altbacken daher. JPivot und auch das Charting machen für meine Begriffe &#8230; <a href="http://cogito-ergo-blog.de/blog/2008/09/30/jboss-seam-mit-mondrian-olap/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Der <a href="http://mondrian.pentaho.org/" target="_blank">Mondrian </a>OLAP Server, der seit einer Weile zur Pentaho-Suite gehört, kann mit einer recht leistungsfähigen Implementierung von Data-Cubes und der <a href="http://msdn.microsoft.com/en-us/library/ms145514.aspx" target="_blank">MDX</a>-Abfragesprache aufwarten.</p>
<p>Allerdings kommt die mitgelieferte Oberfläche etwas altbacken daher. <a href="http://jpivot.sourceforge.net/" target="_blank">JPivot </a>und auch das Charting machen für meine Begriffe nicht viel her. Auch die eingesetzte Web-Technologie ist eher von gestern: JSPs und Taglibs oder ein selten genutztes Web Framework <a href="http://jpivot.sourceforge.net/wcf/index.html" target="_blank">WCF</a>.</p>
<p>Da wurde bei mir schnell der Wunsch wach, Mondrian in <a href="http://www.seamframework.org/" target="_blank">JBoss SEAM</a> zu integrieren und die Chart evtl. mit <a href="http://teethgrinder.co.uk/open-flash-chart/" target="_blank">Open Flash Chart</a> etwas aufzupeppen.</p>
<p>Der folgende Artikel zeigt den ersten Versuch, ein Anfang ist also gemacht.</p>
<p><span id="more-38"></span></p>
<h2>Taglib gegen Components</h2>
<p>Der erste Ansatz war die alte JSP-Taglib, die unter Faclets sowieso nicht zu nutzen wäre, gegen eine JSF-Componente einzutauschen. Im zweiten Schritt soll dann eine SEAM-Componente hinzu kommen.</p>
<p>Die Mondrian Taglib besteht im Kern aus drei Klassen:</p>
<ol>
<li>QueryTag</li>
<li>TransformTag</li>
<li>ResultCache</li>
<li>DOMBuilder</li>
</ol>
<p>1 und 2 sind echte JSP-Tags, das erstere nimmt die Query entgegen und das zweite rendert mit Hilfe von XSLT daraus HTML-Tabellen.</p>
<p>3 und 4 sind Hilfsklassen zur Resourcenverwaltung und zum Erzeugen eines DOM-Trees aus dem Qurey-Result. Der ResultCache sollte in der Form unter SEAM wohl gar nicht existieren, sondern in eine SEAM-Componente übergehen, aber im ersten Schritt habe ich ihn fast unverändert übernommen.</p>
<p>Neu zu bauen ist eine JSF UIComponent, die an Stelle der JSP-Tags die Anfrage entgegen nimmt und das Ergebnis darstellt. Hierzu leitet man die neue Componente von UIOutput ab, definiert die benötigten Properties und überschreibt zum Rendern der Ausgabe &#8220;encodeEnd&#8221;.</p>
<p>Die Component (oder besser deren Type) registriert man in einer Facelets-Taglib &#8220;mondrian.taglib.xml&#8221; und die Component-Class in der face-config.xml. Da die neue Facelets-Taglib nicht im META-INF eines Jars liegt, macht man sie Facelets explizit durch den Context-Parameter &#8220;FACELETS.libraries&#8221; in der web.xml bekannt.</p>
<h2>Test-Project mit SEAM</h2>
<p>Als nächstes setzt man mit &#8220;seam create-project&#8221; eine SEAM Project auf, fügt wie oben beschrieben, die neue Componente ein und baut einen View, der die neue Componente instanziiert.</p>
<p>Damit Mondrian funktioniert, muss man dem SEAM-Project noch einige Dependecies von Mondrian hinzufügen. Bei der von mir verwendeten Mondrian Version (siehe unten) sind dies:</p>
<ul>
<li>eigenbase-xom.jar</li>
<li>eigenbase-res.jar</li>
<li>eigenbase-properties.jar</li>
<li>mondrian.jar</li>
<li>olap4j.jar</li>
<li>commons-dbcp-1.2.jar</li>
<li>commons-pool-1.2.jar</li>
<li>commons-vfs.jar</li>
<li>commons-math-1.0.jar</li>
<li>javacup.jar</li>
</ul>
<p>Diese trägt man zusätzlich in die von seamgen erzeugte Datei &#8220;deployed-jars-ear.list&#8221; ein und kopiert sie nach &#8220;lib&#8221; im Projekt-Verzeichnis, so werden sie von SEAM beim Deployment automatisch berücksichtig.</p>
<p>Desweiteren muss der von Mondrian verwendete JDBC-Treiber auf dem Classpath verfügbar sein. Dieser kann ggf. auf dem Container selber deployed werden (jboss/lib).</p>
<h2>Weitere Resourcen</h2>
<p>Nun fehlt nur noch wenig bis zur ersten Abfrage:</p>
<ol>
<li>Mondrian benötigt eine Property-Datei mondrian.properties auf dem Classpath. Diese wird einfach aus dem Mondrian-Demo WAR kopiert und auf die Classpath-Root gelegt (neben seam.properties). Damit auch diese Datei beim Deployment berücksichtigt wird, trägt man sie am besten in die build.xml ein.</li>
<li>Das Mondrian-Modell (hier im Beispiel foodmart.xml) muss ebenfalls (am besten auch über den Classpath) auffindbar sein. Gleiches Spiel wie eben.</li>
<li>Der connectString zum Mondrian-Server muss als Context-Parameter in der web.xml eingetragen werden.</li>
<li>Da die Componente (vorerst) wie das alte Tag ein XSL-Stylesheet verwendet, um das Ergebnis nach HTML zu wandeln, muss auch das Stylesheet als Classpath-Resource ladbar sein.</li>
</ol>
<p>Der Pfad zum Modell im ConnectString muss übrigens mit &#8220;res:&#8221; beginnen, damit Mondrian, was das VFS von Apache Commons nutzt, die XML-Resource auch findet.</p>
<h3>Versionen</h3>
<p>Die Versionen, die genutzt habe, sind: JBoss 4.2.2.GA, Seam 2.0.2.SP1 und Mondrian-3.0.4.11371-embedded. Das komplette Projekt gibt demnächst hier zum Download.</p>
<h3>Ausblick</h3>
<p>Wie schon in der Einleitung geschrieben, reizt mich vor allen das <strong>Charting </strong>mit Open Flash Chart zu machen. Eine weitere Chart-Componente muss also her, die Ergebnisse aus Mondrian direkt als Chart rendern kann.</p>
<p>Weiterhin ist natürlich die Resourcen-Verwaltung in dieser ersten Fassung nicht gerade SEAM-like, werde ich noch ändern. Und schliesslich ist die Componente natürlich etwas sehr statisch. In SEAM im RichFaces wünscht man sich ja was geAJAXtes wo der Drill-Down und das Pivoting nur so flutsch &#8230;</p>
<p>Mal sehn wann das nächste mal Zeit für sowas ist.</p>
<p>Das <a href="http://www.stefan-rinke.de/download/seam_mondrian.zip">Archiv </a>enthält ein komplettes Projekt (frisch mit seamgen erzeugt), ergänzt um alles was in diesem Artikel erwähnt ist. Wegen der Downloadgrösse fehlen lediglich alle *.class, alle *.jar und alle *.dat Dateien von der Derby-DB.</p>
<p align="baseline">Wenn komplett gebaut und deployed ist, das sieht das ganze so aus:<a href="/blog/wp-content/uploads/seam_mondrian.png"><img class="alignleft size-full wp-image-10026" title="seam_mondrian" src="/blog/wp-content/uploads/seam_mondrian.png" alt="" width="630" height="543" /></a></p>
<p>BTW: An dieser Lösung ist nichts SEAM-spezifisch, alles geht natürlich auch mit Plain-JSF. Da ich aber immer mit Facelets arbeite, habe ich keine JSP-Tag Unterstützung vorgesehen.</p>]]></content:encoded>
			<wfw:commentRss>http://cogito-ergo-blog.de/blog/2008/09/30/jboss-seam-mit-mondrian-olap/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Richtiges Many-To-Many mit Grails</title>
		<link>http://cogito-ergo-blog.de/blog/2008/08/01/richtiges-many-to-many-mit-grails/</link>
		<comments>http://cogito-ergo-blog.de/blog/2008/08/01/richtiges-many-to-many-mit-grails/#comments</comments>
		<pubDate>Fri, 01 Aug 2008 18:54:43 +0000</pubDate>
		<dc:creator>steve40</dc:creator>
				<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://euve3303.vserver.de/stefan/blog/?p=39</guid>
		<description><![CDATA[Will man mit GRAILS ein Real-World-System beschreiben und dabei das schnelle Erstellen von CRUD-Applikationen nutzen, steht man schnell vor dem Problem dass damit Many-To-Many Verknüpfungen nicht gehen. Es wird zwar angeboten, wie bei One-To-Many, aber wenn „Add &#8230;“ gewählt wird, &#8230; <a href="http://cogito-ergo-blog.de/blog/2008/08/01/richtiges-many-to-many-mit-grails/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p style="margin-bottom: 0cm;">Will man mit GRAILS ein Real-World-System beschreiben und dabei das schnelle Erstellen von CRUD-Applikationen nutzen, steht man schnell vor dem Problem dass<br />
damit Many-To-Many Verknüpfungen nicht gehen.</p>
<p style="margin-bottom: 0cm;">Es wird zwar angeboten, wie bei One-To-Many, aber wenn „Add &#8230;“ gewählt wird, kann zwar ein neues Child angelegt werden, aber die Verbindung wird nicht<br />
hergestellt.</p>
<p style="margin-bottom: 0cm;">Auch beim One-To-Many gibt es auf der Many-Side Einschränkungen: es kann nur ein Child per „Add &#8230;“ hinzugefügt werden. Weder wird das Zuordnen eines bereits<br />
angelegten Childs ermöglicht, noch wird das Löschen angeboten.</p>
<p style="margin-bottom: 0cm;">Ausserdem ist die Doku nicht konsistent: Beim Domain-Mapping mit GORM heißt es:</p>
<p style="margin-left: 1.25cm; margin-bottom: 0cm;">„Grails supports many-to-many relationships by defining a <code>hasMany</code> on both<br />
sides of the relationship and having a <code>belongsTo</code> on the side that owns the relationship“.</p>
<p style="margin-bottom: 0cm;">Richtig ist aber das <code>belongsTo</code> gehört auf die Child-Side, nicht auf die Parent-Side, so wie es auch im zugehörigen Beispiel ist.</p>
<p style="margin-bottom: 0cm;">Wichtig ist hier nämlich:</p>
<p style="margin-left: 1.25cm; margin-bottom: 0cm;">„The owning side of the relationship, in this case <code>Author</code>, takes<br />
responsibility for persisting the relationship and is the only side<br />
that can cascade saves across.“</p>
<p style="margin-bottom: 0cm;">Also nur die Parent-Side hat den Cascading-Save und somit sollte nur von dort aus geändert werden. Jedenfalls werden nur die von der Parent-Side ausgemachten<br />
Änderungen ohne weiteres persistiert. Würde man von der Client-Side aus ändern, dann müßte die zugehörige Änderung im Parent explizit gesetzt und persistiert werden.</p>
<p style="margin-bottom: 0cm;">Um die Unterstützung für Many-To-Many in den mit Scaffolding generierten Views zu bekommen, sind die Templates anzupassen. Wie das geht beschreibt der folgende<br />
Artikel.</p>
<p><span id="more-37"></span></p>
<p style="margin-bottom: 0cm;">Viel von den folgenden Codeschnipseln und Konzepten ist durch andere Artikel inspiriert (siehe Referenzen). Was hier zusätzlich dargestellt wird, ist die komplette Logik zu<br />
generieren auch in den Controllern. Und zu guter letzt ist ein komplettes Beispiel beigefügt.</p>
<p style="margin-bottom: 0cm;">Der erste Schritt für eigene, angepasste Templates ist immer:</p>
<p style="margin-bottom: 0cm;"><span style="font-family: courier new,courier,monospace;">grails install-templates</span></p>
<p style="margin-bottom: 0cm;">Damit kopiert <a href="http://www.grails.org/">GRAILS</a> die Standard-Templates lokal ins Projekt und benutzt fortan diese.</p>
<p style="margin-bottom: 0cm;">Dann sucht man im Verzeichnis src/templates/scaffolding das renderEditor.template. Dieses ist für das Erzeugen der Edit-Controls für die einzelnen Properties<br />
einer Domain-Klasse zuständig.</p>
<p style="margin-bottom: 0cm;">Hier gibt es eine Methode „renderOneToMany“, die zunächst eine Liste der bereits<br />
verknüpften Objekte mit Link auf deren „Show“-Url ausgibt und dann das schon bekannte „Add &#8230;“ anbietet. Dieses „Add“ wird durch folgende Zeile erzeugt:</p>
<pre class="brush: groovy; title: ; notranslate">
if( property.oneToMany ) {
    pw.println
&quot; &lt;span
class=\&quot;buttons\&quot;&gt;&lt;g:link
   controller=\&quot;${property.referencedDomainClass.propertyName}\&quot;
params=\&quot;['${domainClass.propertyName}.id':${domainClass.propertyName}?.id]\&quot;
action=\&quot;create\&quot;  class=\&quot;create\&quot;&gt;Add&lt;/g:link&gt;&lt;/span&gt;&quot;
 }
 if( property.isOwningSide() ) {
 	pw.println
&quot; &lt;span
class=\&quot;buttons\&quot;&gt;&lt;g:link
controller=\&quot;${property.referencedDomainClass.propertyName}\&quot;
params=\&quot;['${domainClass.propertyName}.id':${domainClass.propertyName}?.id,
'source':'${domainClass.propertyName}',
'class':'${property.referencedDomainClass.name}',
'dest':'${property.name}','callback':'link']\&quot;
action=\&quot;list\&quot; class=\&quot;save\&quot;&gt;Assoc&lt;/g:link&gt;&lt;/span&gt;&quot;;
 	pw.println
&quot; &lt;span
class=\&quot;buttons\&quot;&gt;&lt;g:link
controller=\&quot;${property.referencedDomainClass.propertyName}\&quot;
params=\&quot;['${domainClass.propertyName}.id':${domainClass.propertyName}?.id,
'source':'${domainClass.propertyName}',
'class':'${property.referencedDomainClass.name}',
'dest':'${property.name}','callback':'unlink']\&quot;
action=\&quot;list\&quot; class=\&quot;delete\&quot;&gt;Remove&lt;/g:link&gt;&lt;/span&gt;&quot;;
 }
</pre>
<p>Dadurch werden zusätzlich ein „Assoc &#8230;“ zum Verbinden und ein „Remove &#8230;“ angeboten, falls man von der „Owning-Side“ aus das Objekt editiert.</p>
<p style="margin-bottom: 0cm;">Somit kann man einerseits auch beim One-To-Many die Assoziation vom Parent aus direkt ändern. Aber – viel wichtiger – Many-To-Many funktioniert so endlich wie<br />
gewünscht.</p>
<p style="margin-bottom: 0cm;">Um das Bild komplett zu machen, fehlen allerdings noch zwei Bausteine. Die neuen Buttons „Assoc“ und „Remove“ leiten zunächst beide zur „List“-Action der verknüpften Klasse weiter, somit wird der normale List-View verwendet, um das Element auszuwählen, welches verknüpft bzw. gelöscht werden soll. Damit diese Auswahl funktioniert, muss der List-View entsprechend erweitert werden. Im Template<br />
list.gsp wird der „Show“-Link:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;g:link action=&quot;show&quot; id=&quot;\${${propertyName}.id}&quot;&gt;
	\${fieldValue(bean:${propertyName}, field:'${p.name}')}
&lt;/g:link&gt;
</pre>
<p>fallweise durch einen „Choose“-Link ersetzt:</p>
<pre class="brush: xml; title: ; notranslate">
&lt;g:if test=&quot;\${params.callback}&quot;&gt;
  &lt;g:link action=&quot;choose&quot; params=&quot;\${params}&quot; id=&quot;\${${propertyName}.id}&quot;&gt;
      \${${propertyName}.${p.name}?.encodeAsHTML()}
  &lt;/g:link&gt;
&lt;/g:if&gt;

&lt;g:if test=&quot;\${!params.callback}&quot;&gt;
  &lt;g:link action=&quot;show&quot; id=&quot;\${${propertyName}.id}&quot;&gt;
     \${${propertyName}.${p.name}?.encodeAsHTML()}
  &lt;/g:link&gt;
&lt;/g:if&gt;
</pre>
<p style="margin-bottom: 0cm;">Dies geschieht – wie man sieht – immer dann, wenn der Callback-Parameter gesetzt ist. Dieser Callback-Parameter wiederum beschreibt, was das „Choose“ jeweils bewirken soll, nämlich entweder ein „Link“ oder ein „Unlink“. Damit das so funktioniert leitet die „Choose“-Action im Controller jeweils auf die „Link“ oder „Unlink“-Action weiter.</p>
<h3>Controller-Templates</h3>
<p style="margin-bottom: 0cm;">Diese drei neuen Actions sind in den standardmässig generierten Controllern nicht vorhanden. Auch hier muss also das Template für den Controller angepasst werden.</p>
<p style="margin-bottom: 0cm;">Das Template für die Controller findet sich ebenso unter src/templates/scaffolding und heißt Controller.groovy. Hier werden am Ende die folgenden Zeilen eingefügt:</p>
<pre class="brush: groovy; title: ; notranslate">
def choose = {
   redirect(controller:params.source,action:params.callback,params:params)
}

def link = {  def ${propertyName} = ${className}.get(params[&quot;${propertyName}.id&quot;])
def toLink = grailsApplication.getClassForName( params[&quot;class&quot;]).get(params[&quot;id&quot;])
def d = params['dest']
  ${propertyName}.&quot;\${d}&quot;.add( toLink );
  render(view:'edit',model:[${propertyName}:${propertyName}])
}

def unlink = {  def ${propertyName} = ${className}.get(params[&quot;${propertyName}.id&quot;])
def toUnlink = grailsApplication.getClassForName( params[&quot;class&quot;]).get(params[&quot;id&quot;])
def d = params['dest']
  ${propertyName}.&quot;\${d}&quot;.remove( toUnlink );
  render(view:'edit',model:[${propertyName}:${propertyName}])
}
</pre>
<p style="margin-bottom: 0cm;">Mit den „Link“ und „Unlink“ Actions kann jeder Controller zwischen beliebigen Domain-Klassen per „add“ und „remove“ Verbindungen erzeugen oder wieder entfernen.</p>
<p style="margin-bottom: 0cm;">Mit diesen drei – eigentlich minimalen – Änderungen funktionieren nun auch Many-To-Many Verknüpfungen mit GRAILS und Scaffolding out of the box.</p>
<h3>Ausblick</h3>
<p style="margin-bottom: 0cm;">Mit der vorgeschlagenen Lösung wird zur Auswahl beim Löschen und Verknüpfen der List-View „missbraucht“. Das ist nicht in jedem Fall optimal. Denkbar wäre auch ein eigener Choose-View, der eine schönere Darstellung hat evtl. auch im Popup-Fenster.</p>
<p style="margin-bottom: 0cm;">Eine weitere Unschönheit ist die Tatsache, dass der List-View auch beim Löschen immer alle Elemente anzeigt und nicht nur die aktuell verknüpften.</p>
<h3>Referenzen</h3>
<p style="margin-bottom: 0cm;"><a href="http://www.ibm.com/developerworks/web/library/j-grails04158/index.html">http://www.ibm.com/developerworks/web/library/j-grails04158/index.html</a></p>
<p style="margin-bottom: 0cm;"><a href="http://www.stainlesscode.com/site/comments/grails_one_to_many_scaffolding/">http://www.stainlesscode.com/site/comments/grails_one_to_many_scaffolding/</a></p>
<p style="margin-bottom: 0cm;"><a href="http://reverttoconsole.com/2008/06/grails-manytomany-gorm-example/">http://reverttoconsole.com/2008/06/grails-manytomany-gorm-example/</a></p>
<h3>Beispiel</h3>
<p style="margin-bottom: 0cm;">Download <a href="/blog/uploads/grails-demo.rar">hier</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://cogito-ergo-blog.de/blog/2008/08/01/richtiges-many-to-many-mit-grails/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>BartPE für Akoya Mini vom USB-Stick</title>
		<link>http://cogito-ergo-blog.de/blog/2008/07/10/bartpe-fur-akoya-mini-vom-usb-stick/</link>
		<comments>http://cogito-ergo-blog.de/blog/2008/07/10/bartpe-fur-akoya-mini-vom-usb-stick/#comments</comments>
		<pubDate>Thu, 10 Jul 2008 16:35:36 +0000</pubDate>
		<dc:creator>steve40</dc:creator>
				<category><![CDATA[Netbook]]></category>

		<guid isPermaLink="false">http://euve3303.vserver.de/stefan/blog/?p=34</guid>
		<description><![CDATA[Für die neuen Netbooks ein Notfall-System zu haben ist nicht so einfach wie man zunächst denkt: es fehlt ja das optische Laufwerk. Damit sind sämtliche Notfall-CDs wie Knoppix oder BartPE, die noch im Schrank liegen, erst mal wertlos. Inzwischen booten &#8230; <a href="http://cogito-ergo-blog.de/blog/2008/07/10/bartpe-fur-akoya-mini-vom-usb-stick/">Weiterlesen <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Für die neuen Netbooks ein Notfall-System zu haben ist nicht so einfach wie man zunächst denkt: es fehlt ja das optische Laufwerk.
</p>
<p>
Damit sind sämtliche Notfall-CDs wie Knoppix oder BartPE, die noch im Schrank liegen, erst mal wertlos. Inzwischen booten aber auch alle Systeme von USB, so auch das neue Akoya mini Netbook. Also schnell das gewünschte BartPE System auf USB übertragen (siehe FAQ bzw. pe2usb.txt im aktuellen BartPE) und los.
</p>
<p>
Bootet auch, alles bestens, nur leider ist die Harddisk nicht zu finden: Die interne SATA-Platte braucht einen Treiber, damit WinXP darauf zugreifen kann.
</p>
<p>
Um dieses Problem zu umschiffen, mußte ich eine ganze Weile rumgoogeln, bis klar war wie&#8217;s geht, deshalb hier kurz die Schritt für Schritt Anleitung.
</p>
<p><span id="more-36"></span>
<p>Ein BartPE zu erstellen erfordert immer die Installationsdateien von Windows mit SP2 oder grösser bereits &#8220;geslipstreamed&#8221;. Zum Glück hat der Akoya alle Installationsdateien im Windows-Verzeichnis bereits abgelegt (von CD holen geht ja nicht <img src='http://cogito-ergo-blog.de/blog/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  )</p>
<h2>Schritt 1: BartPE herunterladen und konfigurieren</h2>
<p>Einfach BartPE von <a href="http://www.nu2.nu/pebuilder/">http://www.nu2.nu/pebuilder/</a> herunter laden und Quellverzeichnis auf c:\windows einstellen.</p>
<p>Nach dem Durchlaufen des Builders pe2usb.cmd aufrufen mit dem Laufwerk des Sticks als Parameter (eventuell den Stick mit -f noch formatieren) und fertig. Nur leider noch ohne Zugriff auf die Platte.</p>
<h2>Schritt 2: F6-Treiber &#8220;Diskette&#8221; erzeugen</h2>
<p>Auf der Wiederherstellungspartition D: findet sich im Verzeichnis DRIVERS/AHCI eine Datei f6flpy32.exe, die nach dem Namen geraten die F6-Diskette erzeugen könnte. Ein Starten bewirkt aber leider gar nichts, nicht mal eine Fehlermeldung.</p>
<p>Mehr durch Zufall stellt man fest, dass das EXE ein WinImage Self-Extractor File ist (zeigt der Explorer-Tooltip) und das man dass mit WinRar auspacken kann. Heraus kommt ein Disketten-Image unschwer an der Dateigrösse von 1.440 KB zu erkennen.</p>
<h2>Schritt 3: Dateien extrahieren</h2>
<p>Leider kann man das Image auch nicht so leicht auf Diskette schreiben, weil sowas hat das Netbook natürlich schon dreimal nicht. Also muss man nur noch die Files aus dem Image extrahieren z.B. mit <a href="http://www.magiciso.com/">MagicISO</a> und diese Files an die richtige Stelle ins BartPE Builder Verzeichnis kopieren und schon &#8230; geht&#8217;s.
</p>
<h2>Schritt 4: BartPE erweitern</h2>
<p>Die richtige Stelle ist schnell gefunden. Im BartPE Verzeichnis Drivers in SCSIAdapter ein Verzeichnis &#8220;sata&#8221; anlegen und dort die Dateien der &#8220;F6&#8243;-Diskette rein, den PEBuilder nochmal durchlaufen lassen, alles auf den USB-Stick und Heureka!!! es geht.</p>
<h2>Abkürzung</h2>
<p>Den Inhalt der F6-Diskette findet ihr in diesem<br />
<a href="/blog/uploads/sata.zip" title="sata.zip" target="_blank">Zip</a>, so dass die Abkürzung einfach lautet:</p>
<ul>
<li>Zip in BartPE/Drivers/SCSIAdapter entpacken</li>
<li>PEBuilder durchlaufen lassen</li>
<li>mit pe2usb.cmd auf den Stick kopieren</li>
</ul>
<p>
Mit diesem BartPE kann man dann auch ganz schnell aus dem Windows XP Home Edition eine Professionell machen, wie das läßt z.B. in der CT 13/2008 auf Seite 188 nachlesen.
</p></p>]]></content:encoded>
			<wfw:commentRss>http://cogito-ergo-blog.de/blog/2008/07/10/bartpe-fur-akoya-mini-vom-usb-stick/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

