<?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>blog.dennis.io</title>
	<atom:link href="http://blog.dennis.io/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.dennis.io</link>
	<description>... geek and proud of it</description>
	<lastBuildDate>Thu, 08 Dec 2011 18:34:18 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>phpUnit und Klassen mit __call</title>
		<link>http://blog.dennis.io/phpunit-und-klassen-mit-__call/</link>
		<comments>http://blog.dennis.io/phpunit-und-klassen-mit-__call/#comments</comments>
		<pubDate>Thu, 08 Dec 2011 18:34:18 +0000</pubDate>
		<dc:creator>dennis</dc:creator>
				<category><![CDATA[coding]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[tdd]]></category>
		<category><![CDATA[phpunit]]></category>
		<category><![CDATA[__call]]></category>

		<guid isPermaLink="false">http://blog.dennis.io/?p=386</guid>
		<description><![CDATA[Nutzt man phpUnit mit Klassen die MagicMethods wie z.B. __call() enthalten ist Vorsicht geboten. Ich habe gerade recht lange gebraucht um herauszufinden, warum folgender Test nicht funktioniert. Zunächst zwei Klassen, eine davon definieren wir als abstract class: &#60;?php class AnotherRealObject { public function __call($method, $args) { return 'AnotherRealObject->'.$method.'()'; } } abstract class SomeAbstractClassWithConcreteMethods { private [...]]]></description>
			<content:encoded><![CDATA[<p>Nutzt man phpUnit mit Klassen die MagicMethods wie z.B. __call() enthalten ist Vorsicht geboten. Ich habe gerade recht lange gebraucht um herauszufinden, warum folgender Test nicht funktioniert.</p>

<p>Zunächst zwei Klassen, eine davon definieren wir als <em>abstract class</em>:</p>

<div><pre class="brush:php">
&lt;?php
    class AnotherRealObject {
    
        public function __call($method, $args) {
            return 'AnotherRealObject->'.$method.'()'; 
        }
    
    }

    abstract class SomeAbstractClassWithConcreteMethods {

        private $anotherObject;
    
        abstract public function abstractMethod();
    
       public function concreteMethodToSetObject($o) {
            $this->anotherObject = $o;
        }

        public function concreteMethod() {
            return $this->anotherObject->aMethod();
        }
    
    }        
?&gt;   
</pre></div>

<p><span id="more-386"></span>
Soweit nichts aufregendes. AnotherRealObject enthält lediglich eine Methode, die bei einem beliebigen Methoden-Aufruf einen String zurückgibt, der angibt welche Methode auf dem Objekt aufgerufen wurde. Mal kurz in einer interaktiven PHP-Shell getestet sieht das ganze so aus:</p>

<div><pre class="brush:bash">
    php > $stub = new AnotherRealObject();
    php > echo $stub->blubb();
    AnotherRealObject->blubb()
    php > echo $stub->someMethodWithAnArbitraryName();
    AnotherRealObject->someMethodWithAnArbitraryName()  
</pre></div>

<p>Die zweite Klasse ist abstract definiert. Das hat für diesen Beitrag keinen besonderen Grund, ich wollte in meinen Tests einfach nur ausschließen, dass das Problem darauf zurückzuführen ist. Die Klasse hat zwei konkrete Methoden. Eine zum Setzen der Abhängigkeit $anotherObject und eine weitere, die auf diesem Objekt eine Methode aufruft und deren Rückgabewert zurückgibt.</p>

<p>Ein phpUnit Test um die abstrakte Klasse zu testen könnte wie folgt aussehen:</p>

<div><pre class="brush:php">
    class phpUnitBugTest extends PHPUnit_Framework_TestCase {

        private $uut;
        private $stub;

        public function setUp() {

            $this->uut = $this->getMockForAbstractClass('SomeAbstractClassWithConcreteMethods');

            $this->stub = $this->getMock('AnotherRealObject');
            $this->stub->expects( $this->any() )
                          ->method('aMethod')
                       ->will ( $this->returnValue('StubOfAnotherRealObject->aMethod()') );

            $this->uut->concreteMethodToSetObject($this->stub);
        }


        public function testBug() {
            $this->assertEquals('StubOfAnotherRealObject->aMethod()', $this->uut->concreteMethod());
        }


    }
</pre></div>

<p>Mit der durch phpUnit bereitgestellten Methode <em>getMockForAbstractClass()</em> instanzieren wir eine Instanz der abstrakten Klasse (das Testobjekt). Außerdem instanzieren wir ein Stub von <em>AnotherRealObject</em> und legen fest, dass beim Aufruf der Methode <em>aMethod</em> auf diesem Stub der String <em>StubOfAnotherRealObject->aMethod()</em> zurückgegeben wird. Anschließend wird das Stub noch in die Instanz der abstrakten Klasse injected.</p>

<p>Soweit so gut &#8211; fehlt der eigentliche Test. Was sollte passieren, wenn auf dem TestObjekt die Methode <em>concreteMethod()</em> aufgerufen wird? Nun ja, die Methode ruft auf dem Feld $anotherObject die Methode <em>aMethod</em> auf. Dem Feld <em>$anotherObject</em> ist unser Stub zugewiesen und dem Stub haben wir gesagt, dass es beim Aufruf von <em>anotherMethod</em> den String <em>StubOfAnotherRealObject->aMethod()</em> zurückgeben soll. Dementsprechend sollte ein aufruf von <em>concreteMethod()</em> genau diesen String zurückliefern.</p>

<p>Leider spielt phpUnit hier nicht mit. Der Test schlägt fehl:</p>

<div><pre class="brush:bash">
    There was 1 failure:

    1) phpUnitBugTest::testBug
    Failed asserting that two strings are equal.
    --- Expected
    +++ Actual
    @@ @@
    -StubOfAnotherRealObject->aMethod()
    +

    dev/phpUnitBugTest.php:45   
</pre></div>

<p>Wie man sieht gibt es gar keinen Rückgabewert. 
Aber warum ist das so? PhpUnit erstellt nur Method-Stubs für Methoden, die es tatsächlich in der Klasse gibt. Die Methode <em>aMethod</em> gibt es aber nicht wirklich, also erstellt phpUnit auch kein Stub dafür. Es gibt allerdings eine einfache Lösung für das Problem &#8211; auch wenn ich sie nicht besonders schön finde: Man sagt phpUnit einfach explizit, dass es einen Stub für die Methode <em>aMethod</em> erstellen soll. Dies geschieht beim erzeugen des Stubs:</p>

<div><pre class="brush:php">
    $this->stub = $this->getMock('AnotherRealObject', array('aMethod'));
</pre></div>

<p>Mit dieser Änderung läuft der Test durch. Aber Vorsicht: PhpUnit erstellt jetzt nur Stubs, die durch den Parameter festgelegt wurden. D.h. es müssen alle Methoden in diesem Array übergeben werden, für die Subs angelegt werden sollen &#8211; egal ob diese in der eigentlichen Klassen existieren oder nicht. Und genau dies ist auch der Grund, warum ich diese Lösung nicht schön finde.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.dennis.io/phpunit-und-klassen-mit-__call/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mockito und Maps</title>
		<link>http://blog.dennis.io/mockito-und-maps/</link>
		<comments>http://blog.dennis.io/mockito-und-maps/#comments</comments>
		<pubDate>Thu, 14 Apr 2011 14:21:54 +0000</pubDate>
		<dc:creator>dennis</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[tdd]]></category>
		<category><![CDATA[compareTo]]></category>
		<category><![CDATA[equals]]></category>
		<category><![CDATA[hashCode]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[mockito]]></category>

		<guid isPermaLink="false">http://blog.dennis.io/?p=385</guid>
		<description><![CDATA[Ich schreibe gerade einige Tests für das Java Projekt meiner Master Arbeit. Dabei arbeite ich auch zum ersten Mal mit dem Mocking Framework Mockito. Im Zusammenhang mit Mockito musste ich eben einen wichtigen Unterschied zwischen einer HashMap und einer TreeMap lernen. Wenn man mit Mockito ein Objekt mockt, stellt das Framework automatisch stubs für equals() [...]]]></description>
			<content:encoded><![CDATA[<p>Ich schreibe gerade einige Tests für das Java Projekt meiner Master Arbeit. Dabei arbeite ich auch zum ersten Mal mit dem Mocking Framework <a href="http://mockito.org/" title="">Mockito</a>. Im Zusammenhang mit Mockito musste ich eben einen wichtigen Unterschied zwischen einer HashMap und einer TreeMap lernen.</p>

<p><span id="more-385"></span>
Wenn man mit Mockito ein Objekt mockt, stellt das Framework automatisch <a href="http://de.wikipedia.org/wiki/Stub_&#40;Programmierung&#41;" title="">stubs</a> für equals() und hashCode() bereit. Deshalb läuft folgender <a href="http://www.junit.org/" title="">JUnit</a> Test ohne Fehler durch:</p>

<div><pre class="brush:java">
@Test
public void testMockito() {

    BigDecimal o1 = mock(BigDecimal.class);
    BigDecimal o2 = mock(BigDecimal.class);

    assertEquals(false, o1.equals(o2));
}
</pre></div>

<p>Da Mockito sich also um equals() und hashCode() kümmert kann man ge&#8217;mockte Objekte auch einfach mit einer Map benutzen. Dazu zum Beispiel folgender Test:</p>

<div><pre class="brush:java">
@Test
public void testMockitoWithHashMap() {

    BigDecimal o1 = mock(BigDecimal.class);
    BigDecimal o2 = mock(BigDecimal.class);

    Map&lt;BigDecimal, String&gt; map = new HashMap&lt;BigDecimal, String&gt;();
    map.put(o1, &quot;erster Mock&quot;);

    assertEquals(true, map.containsKey(o1));
    assertEquals(false, map.containsKey(o2));   
}
</pre></div>

<p>Läuft. Super. Aber Vorsicht. Der gleiche Test mit einer TreeMap schlägt fehl:</p>

<div><pre class="brush:java">
@Test
public void testMockitoWithTreeMap() {

    BigDecimal o1 = mock(BigDecimal.class);
    BigDecimal o2 = mock(BigDecimal.class);

    Map&lt;BigDecimal, String&gt; map = new TreeMap&lt;BigDecimal, String&gt;();
    map.put(o1, &quot;erster Mock&quot;);

    assertEquals(true, map.containsKey(o1));
    assertEquals(false, map.containsKey(o2));   
}
</pre></div>

<p>So sieht die Fehlermeldung dazu aus:</p>

<div><pre class="brush:java">
java.lang.AssertionError: expected:&lt;false&gt; but was:&lt;true&gt;
    [...]
    at [...].testMockitoWithTreeMap(Test.java:92)
    [...]
</pre></div>

<p>Erfahrene Java Entwickler wissen natürlich sofort was hier los ist. Für alle anderen dürfte es nach einem Blick in die <a href="http://download.oracle.com/javase/6/docs/api/java/util/TreeMap.html#TreeMap&#40;&#41;" title="">API von TreeMap</a> klar werden:</p>

<blockquote>
  <p>Note that the ordering maintained by a sorted map (whether or not an explicit comparator is provided) must be consistent with equals if this sorted map is to correctly implement the Map interface. (See Comparable or Comparator for a precise definition of consistent with equals.) This is so because the Map interface is defined in terms of the equals operation, but a map performs all key comparisons using its compareTo (or compare) method, so two keys that are deemed equal by this method are, from the standpoint of the sorted map, equal. The behavior of a sorted map is well-defined even if its ordering is inconsistent with equals; it just fails to obey the general contract of the Map interface.</p>
</blockquote>

<p>Was bedeutet dies für das Mocking mit Mockito? Beim Aufruf von <em>map.containsKey(o2)</em> im letzten Test oben, wird intern irgendwann <em>o2.compareTo(o1)</em> aufgerufen. Im Interface <em>java.lang.Comparable</em> ist die Methode wie folgt definiert:</p>

<div><pre class="brush:java">int compareTo(T o)</pre></div>

<blockquote>
  <p>Compares this object with the specified object for order. Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.</p>
</blockquote>

<p>Da Mockito versucht sinnvolle Rückgabewerte zu erzeugen, wird der Aufruf von <em>o2.compareTo(o1)</em> &#8220;0&#8243; zurückgeben. 0 bedeutet aber in diesem Fall das o1 und o2 gleich sind. Deshalb liefert der Aufruf von <em>map.containsKey(o2)</em> auch ein <strong><em>true</em></strong>.</p>

<p>Ein kleiner Test dazu:</p>

<div><pre class="brush:java">
@Test
public void testMockitoWithTreeMapAndVerifyCompareToCall() {

    BigDecimal o1 = mock(BigDecimal.class);
    BigDecimal o2 = mock(BigDecimal.class);

    Map&lt;BigDecimal, String&gt; map = new TreeMap&lt;BigDecimal, String&gt;();
    map.put(o1, &quot;erster Mock&quot;);

    assertEquals(true, map.containsKey(o1));

    verify(o2, times(0)).compareTo(o1);
    map.containsKey(o2);
    verify(o2, times(1)).compareTo(o1);
}
</pre></div>

<p>Mit diesem Wissen können wir den Test von weiter oben umschreiben, so dass auch dieser durchläuft:</p>

<div><pre class="brush:java">
@Test
public void testMockitoWithTreeMap() {

    BigDecimal o1 = mock(BigDecimal.class);
    BigDecimal o2 = mock(BigDecimal.class);

    when(o2.compareTo(o1)).thenReturn(1); // NEU

    Map&lt;BigDecimal, String&gt; map = new TreeMap&lt;BigDecimal, String&gt;();
    map.put(o1, &quot;erster Mock&quot;);

    assertEquals(true, map.containsKey(o1));
    assertEquals(false, map.containsKey(o2));   
} 
</pre></div>

<p>Mit nur einer neuen Zeile läuft der Test von vorhin nun korrekt durch. Der Aufruf von <em>o2.compareTo(o1)</em> liefert nun 1, was bedeutet das o2 &#8220;größer&#8221; ist als o1 und somit nach o1 in der TreeMap eingeordnet wird.</p>

<h3>Fazit</h3>

<p>Für erfahrene Java Entwickler ist dieser Post mit Sicherheit nichts Neues und so wie ich das Problem hier beschrieben habe, ist der Fehler auch sofort ersichtlich. Wenn man allerdings eine Klasse testet die intern eine TreeMap benutzt, nach außen aber nur das Map Interface sichtbar macht, ist ein solcher Fehler nicht gleich ersichtlich und vielleicht verwirrend.</p>

<p>Neben der Erkenntnis über die Implementierungs-Unterschiede zwischen HashMap und TreeMap hat mir dieses Problem heute mal wieder gezeigt, wie wichtig und sinnvoll Testing ist. Durch das Schreiben dieses einen Tests habe ich ein neues Detail der Java API kennengelernt, mich näher mit Mocktio beschäftigt und gleich zwei Probleme in meinen eigenen Klassen gefunden und beseitigen können. So muss das sein! <img src='http://blog.dennis.io/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.dennis.io/mockito-und-maps/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>#gddde Mitbringsel: Spring Roo + GWT</title>
		<link>http://blog.dennis.io/gddde-mitbringsel-spring-roo-gwt/</link>
		<comments>http://blog.dennis.io/gddde-mitbringsel-spring-roo-gwt/#comments</comments>
		<pubDate>Wed, 10 Nov 2010 17:20:37 +0000</pubDate>
		<dc:creator>dennis</dc:creator>
				<category><![CDATA[GWT]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Spring Roo]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[gwt]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[springroo]]></category>

		<guid isPermaLink="false">http://blog.dennis.io/?p=384</guid>
		<description><![CDATA[Ich war gestern zusammen mit @marcwerner auf dem Google Developer Day in München. Sehr nette Veranstaltung von Google, auf der Vorträge zu Google Technologien gehalten werden und es lecker Essen gibt . Im ersten Vortrag den ich mir angehört habe ging es um Spring Roo und das Google Web Toolkit. Sehr spannende Sache, da ich [...]]]></description>
			<content:encoded><![CDATA[<p>Ich war gestern zusammen mit <a href="http://twitter.com/#!/marcwerner">@marcwerner</a> auf dem <a href="http://www.google.com/intl/de_ALL/events/developerday/2010/munich/index.html" title="Google Developer Day 2010">Google Developer Day in München</a>. Sehr nette Veranstaltung von Google, auf der Vorträge zu Google Technologien gehalten werden und es lecker Essen gibt <img src='http://blog.dennis.io/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . Im ersten Vortrag den ich mir angehört habe ging es um <a href="http://www.springsource.org/roo" title="Spring Roo | SpringSource.org">Spring Roo</a> und das <a href="http://code.google.com/webtoolkit/" title="Google Web Toolkit - Google Code">Google Web Toolkit</a>. Sehr spannende Sache, da ich zur Entwicklung von WebApps sowieso vorhatte von PHP auf Java zu wechseln. Den Vortrag hielt <a href="http://www.springsource.com/people/cdupuis" title="Christian Dupuis | SpringSource">Christian Dupuis</a> von SpringSource. In seiner Demo zeigte er, wie man mit Spring Roo in unter 3 Minuten eine lauffähige WebApp zusammenbaut. Grund genug für mich mir das heute mal selbst anzuschauen und auszuprobieren.</p>

<p><span id="more-384"></span>
Zunächst erstmal alle Tools herunterladen, installieren und konfigurieren. Ich habe mir die <a href="http://www.springsource.com/landing/best-development-tool-enterprise-java" title="Development Tool Suite for Enterprise Java | SpringSource">SpringSource Tool Suite</a> heruntergeladen. Da ist alles dabei, sowohl Spring Roo, als auch <a href="http://maven.apache.org/" title="Maven - 
    Welcome to Apache Maven">Maven</a> und ein Spring Source Server zum lokalen Testen der Anwendungen. Nach dem Entpacken habe ich alles nach ~/Applications/ kopiert (Achtung, das ist kein Standard-Ordner unter OSX &#8211; den habe ich mir für lokale Anwendungen angelegt). Damit man Roo und Maven einfacher benutzen kann, muss das ganze noch in den Pfad aufgenommen werden. Dazu linke ich die Skripte einfach nach /usr/bin:</p>

<div><pre class="brush:bash">
    sudo ln -s /Users/dennis/Applications/roo-1.1.0/bin/roo.sh /usr/bin/roo
    sudo ln -s /Users/dennis/Applications/maven-2.2.1.RELEASE/bin/mvn /usr/bin/mvn
</pre></div>

<p>Achtung, die Pfade könnten bei dir etwas anders sein! Nicht einfach copy/pasten.</p>

<p><a href="http://dl.kips-world.de/misc/sts-dashboard.PNG"><img src="http://blog.dennis.io/thumb.php?file=http://dl.kips-world.de/misc/sts-dashboard.PNG" alt="sts-dashboard" /></a></p>

<p>Im Anschluss habe ich erstmal die SpringSource Tool Suite (STS) gestartet und im Willkommens-Bildschirm über &#8220;Install Extension&#8221; den Support für GWT installiert. Danach möchte STS einmal neu gestartet werden und dann kanns auch schon losgehen. Natürlich kann man jetzt einfach die IDE benutzen und das erste Spring Roo Projekt erstellen, aber ich wollte die Roo Konsole testen &#8211; über die IDE kann das ja jeder <img src='http://blog.dennis.io/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>

<p>Also wieder zurück auf die Konsole, ein neues Verzeichnis im Workspace anlegen und die roo-Shell aufrufen:</p>

<div><pre class="brush:bash">
    cd ~/springroo
    mkdir testApp
    cd testApp
    roo
</pre></div>

<p><a href="http://dl.kips-world.de/misc/roo-console.PNG"><img src="http://blog.dennis.io/thumb.php?file=http://dl.kips-world.de/misc/roo-console.PNG" alt="roo-console" /></a></p>

<p>In der roo-Shell habe ich folgende Befehle ausgeführt:</p>

<div><pre class="brush:bash">
    project --topLevelPackage io.dennis.roo.amawish
    persistence setup --provider HIBERNATE --database HYPERSONIC_IN_MEMORY 
    entity --class ~.domain.Item
    field string --fieldName label
    entity --class ~.domain.Account
    field string --fieldName email
    field set --fieldName items --element ~.domain.Item
    gwt setup
    perform eclipse
    perform clean
</pre></div>

<p>Die Befehle kannst du auch als <a href="http://dl.kips-world.de/misc/setup.roo" title="">roo-Script herunterladen</a> und ausführen. Das Skript einfach in das testApp Verzeichnis kopieren und dann in der <strong>roo-Shell</strong> folgenden Befehl ausführen:</p>

<div><pre class="brush:bash">
    script --file setup.roo
</pre></div>

<p>Wenn das Skript durchgelaufen ist (kann einen Moment dauern) kann man das Projekt am schnellsten über Maven starten. Dazu die roo-Shell verlassen (Command: quit) und Maven seine Arbeit machen lassen:</p>

<div><pre class="brush:bash">
    mvn gwt:run
</pre></div>

<p><a href="http://dl.kips-world.de/misc/roo-maven-gwt.PNG"><img src="http://blog.dennis.io/thumb.php?file=http://dl.kips-world.de/misc/roo-maven-gwt.PNG" alt="roo-maven-gwt" /></a></p>

<p>Jetzt kann man das Projekt im Browser aufrufen. Bei mir sieht das ganze so aus:</p>

<p><a href="http://dl.kips-world.de/misc/roo-gwt-example-application.PNG"><img src="http://blog.dennis.io/thumb.php?file=http://dl.kips-world.de/misc/roo-gwt-example-application.PNG" alt="roo-gwt-example-application" /></a></p>

<p>Das ging schnell oder? Wenn man jetzt an dem Projekt weiterarbeiten möchte kann man es ganz einfach in STS importieren (&#8220;File&#8221; > &#8220;Import&#8221; > &#8220;Existing Projects into Workspace&#8221;).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.dennis.io/gddde-mitbringsel-spring-roo-gwt/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>PHP Getter/Setter Generator</title>
		<link>http://blog.dennis.io/php-gettersetter-generator/</link>
		<comments>http://blog.dennis.io/php-gettersetter-generator/#comments</comments>
		<pubDate>Sat, 30 Oct 2010 13:10:29 +0000</pubDate>
		<dc:creator>dennis</dc:creator>
				<category><![CDATA[coding]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[getter]]></category>
		<category><![CDATA[setter]]></category>

		<guid isPermaLink="false">http://blog.dennis.io/?p=381</guid>
		<description><![CDATA[Ich benutze seit kurzem die PHP Development Tools von Eclipse zum Entwickeln von PHP Code. Eclipse selbst ist eine sehr gute IDE, allerdings hat das PDT Plugin hier und da doch noch einige Schwächen. Zum Beispiel war ich gerade dabei, eine neue Klasse für das IRD Bogenoffset Tool zu schreiben, die insgesamt auf 52 Felder [...]]]></description>
			<content:encoded><![CDATA[<p>Ich benutze seit kurzem die <a href="http://www.eclipse.org/pdt/">PHP Development Tools</a> von <a href="http://www.eclipse.org/" title="Eclipse.org home">Eclipse</a> zum Entwickeln von PHP Code. Eclipse selbst ist eine sehr gute IDE, allerdings hat das PDT Plugin hier und da doch noch einige Schwächen. Zum Beispiel war ich gerade dabei, eine neue Klasse für das <a href="http://ird-online.de/wissen/ird-online-prozessrating/">IRD Bogenoffset Tool</a> zu schreiben, die insgesamt auf 52 Felder kam. Jetzt bin ich es von Java natürlich gewohnt, dass die IDE mir für diese Felder automatisch Getter und Setter generiert &#8211; leider geht das mit den PDT nicht <img src='http://blog.dennis.io/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> .</p>

<p>Nach einer kurzen Google Recherche musste ich feststellen, dass im Netz auch kein brauchbarer PHP Getter/Setter Generator aufzutreiben ist. Also, nicht lange rumdümpeln, schreibe ich mir halt schnell selbst einen &#8211; sowieso die Gelegenheit sich mal die <a href="http://php.net/manual/en/book.reflection.php" title="PHP: Reflection - Manual">PHP Reflection API</a> anzuschauen. Hier das Ergebnis nach 10 Minuten Arbeit:</p>

<div><pre class="brush:php">
#!/usr/bin/php
&lt;?php

    if (!is_file($argv[2])) 
        die('Use this way: '.$argv[0].' &lt;class_name&gt; &lt;path_to_your_class`s_php_file&gt;'."\n");

    require_once($argv[2]);

    $class = new $argv[1]();
    $reflection = new ReflectionClass($argv[1]);
    $fields = $reflection->getProperties(
        ReflectionProperty::IS_PRIVATE
        | ReflectionProperty::IS_PROTECTED
    );

    foreach ($fields AS $f) {

        // getter
        echo 'public function get'.ucfirst($f->getName()).'() {'."\n";
        echo "\t".'return $this->'.$f->getName().';'."\n";
        echo '}'."\n";
        // setter
        echo 'public function set'.ucfirst($f->getName()).'($val) {'."\n";
        echo "\t".'$this->'.$f->getName().' = $val;'."\n";
        echo '}'."\n\n";

    }
    echo 'Generated Getter and Setter for '.count($fields).' fields'."\n\n";
?&gt;   
</pre></div>

<p>Das ganze ist ein PHP-Konsolenscript. Als Parameter den Namen eurer Klasse und den Pfad zur PHP Datei mitgeben in der die Klasse deklariert ist. Als Ausgabe erhält man die Getter- und Setter-Methoden für alle Felder, die als <code>private</code> oder <code>protected</code> deklariert sind. Vielleicht hat ja noch jemand anders Verwendung dafür &#8211; mir hats eine Menge Zeit gespart <img src='http://blog.dennis.io/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.dennis.io/php-gettersetter-generator/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>server move finished. well, kind of.</title>
		<link>http://blog.dennis.io/servermove-finished-well-kind-of/</link>
		<comments>http://blog.dennis.io/servermove-finished-well-kind-of/#comments</comments>
		<pubDate>Fri, 22 Oct 2010 08:30:32 +0000</pubDate>
		<dc:creator>dennis</dc:creator>
				<category><![CDATA[blog]]></category>
		<category><![CDATA[common]]></category>

		<guid isPermaLink="false">http://blog.dennis.io/?p=380</guid>
		<description><![CDATA[Nachdem ich meinen Server nun umgezogen habe und etwas mit Apache/PHP 5.3 zu kämpfen hatte ist der Blog nun wieder online. Das PHP Probleme werde ich in den nächsten Tage noch verbloggen, denn gelöst ist es bis jetzt nicht. Habe nur vorübergehend PHP 5.2 installiert, um den Blog erstmal wieder online zu stellen. Das Theme [...]]]></description>
			<content:encoded><![CDATA[<p>Nachdem ich meinen Server nun umgezogen habe und etwas mit Apache/PHP 5.3 zu kämpfen hatte ist der Blog nun wieder online. Das PHP Probleme werde ich in den nächsten Tage noch verbloggen, denn gelöst ist es bis jetzt nicht. Habe nur vorübergehend PHP 5.2 installiert, um den Blog erstmal wieder online zu stellen. Das Theme hat noch ein paar kleine Schönheitsfehler, aber die repariere ich dann in den nächsten Tagen.</p>

<p>Und weil ich gerade nicht mehr zu erzählen habe, ein kleines Video das ich sehr cool fand (via <a href="http://blog.f00sel.de/">@seb</a>):</p>

<p><object width="640" height="385"><param name="movie" value="http://www.youtube.com/v/u6XAPnuFjJc?fs=1&amp;hl=en_US"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/u6XAPnuFjJc?fs=1&amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.dennis.io/servermove-finished-well-kind-of/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Musik vom iPod in iTunes hören</title>
		<link>http://blog.dennis.io/musik-vom-ipod-in-itunes-horen/</link>
		<comments>http://blog.dennis.io/musik-vom-ipod-in-itunes-horen/#comments</comments>
		<pubDate>Fri, 09 Jul 2010 20:22:30 +0000</pubDate>
		<dc:creator>dennis</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[mac osx]]></category>
		<category><![CDATA[ipod]]></category>
		<category><![CDATA[itunes]]></category>
		<category><![CDATA[musik]]></category>

		<guid isPermaLink="false">http://blog.kips-world.de/?p=372</guid>
		<description><![CDATA[Folgendes Szenario: Ich habe Zuhause einen Mac an dem ich mein iPhone und meinen iPod synchronisiere. Mit anderen Worten: meine komplette Musik befindet sich auf meiner Festplatte Zuhause. Was aber nun wenn ich unterwegs (in der Uni, auf der Arbeit) Musik hören möchte? Bisher habe ich aus diesem Grund meine iTunes Bibliothek regelmäßig über rsync [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://blog.kips-world.de/wp-content/uploads/2010/07/itunes.png" alt="iTunes" /></p>

<p>Folgendes Szenario: Ich habe Zuhause einen Mac an dem ich mein iPhone und meinen iPod synchronisiere. Mit anderen Worten: meine komplette Musik befindet sich auf meiner Festplatte Zuhause. Was aber nun wenn ich unterwegs (in der Uni, auf der Arbeit) Musik hören möchte? Bisher habe ich aus diesem Grund meine iTunes Bibliothek regelmäßig über rsync auf mein MacBook kopiert.</p>

<p><span id="more-372"></span>
Hat aber den Nachteil, dass iPod und iPhone beim Anschließen ans MacBook einen kompletten Sync machen (und das dauert). iTunes auf dem MacBook kennt die Geräte und hält sie für seine eigenen. Da die Bibliothek auf dem MacBook aber in der Regel älter ist als die auf dem Mac Zuhause, wird eben der komplette Sync durchgeführt. Doch dem nicht genug &#8211; sobald die Geräte wieder am Mac Zuhause hängen, geht das ganze von vorne los, nur in die andere Richtung <img src='http://blog.dennis.io/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> </p>

<p>Deshalb die Idee: Wenn ich doch eh mein iPhone + iPod dabei habe, warum nicht die Musik auf dem Gerät über das MacBook hören. Damit dies funktioniert, muss man in iTunes für den iPod die &#8220;Manuelle Verwaltung von Musik und Bildern aktivieren&#8221;.</p>

<p><a href="http://blog.kips-world.de/wp-content/uploads/2010/07/musik_vom_ipod_abspielen.jpg"><img src="http://blog.kips-world.de/thumb.php?file=http://blog.kips-world.de/wp-content/uploads/2010/07/musik_vom_ipod_abspielen.jpg" alt="Musik vom iPod abspielen" /></a></p>

<p>Und schon kann man sein iOS Gerät als tragbare Musik-Bibliothek für OSX benutzen.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.dennis.io/musik-vom-ipod-in-itunes-horen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WakeOnLan beim Starten/Aufwachen</title>
		<link>http://blog.dennis.io/wakeonlan-beim-startenaufwachen/</link>
		<comments>http://blog.dennis.io/wakeonlan-beim-startenaufwachen/#comments</comments>
		<pubDate>Sun, 13 Jun 2010 11:40:59 +0000</pubDate>
		<dc:creator>dennis</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[mac osx]]></category>
		<category><![CDATA[macosx]]></category>
		<category><![CDATA[wakeonlan]]></category>
		<category><![CDATA[windows]]></category>
		<category><![CDATA[wol]]></category>

		<guid isPermaLink="false">http://blog.kips-world.de/?p=352</guid>
		<description><![CDATA[Wir haben in unserem Netzwerk einen Rechner mit Linux der als Router, Firewall, Fileserver und ein paar andere Dinge dient. Der Rechner ist so konfiguriert, dass er ab 0.00 Uhr nachts alle 15 Minuten das lokale Netz überprüft und sich automatisch ausschaltet, sobald kein anderer PC mehr läuft. Auf Client Seite ist unser Netzwerk bunt [...]]]></description>
			<content:encoded><![CDATA[<p>Wir haben in unserem Netzwerk einen Rechner mit Linux der als Router, Firewall, Fileserver und ein paar andere Dinge dient. Der Rechner ist so konfiguriert, dass er ab 0.00 Uhr nachts alle 15 Minuten das lokale Netz überprüft und sich automatisch ausschaltet, sobald kein anderer PC mehr läuft.</p>

<p>Auf Client Seite ist unser Netzwerk bunt gemischt. Mit MacOSX, Linux und Windows sind alle nennenswerten Betriebsysteme vertreten. Nun möchten alle natürlich, dass der Router morgens anspringt sobald der eigene Rechner eine Internetverbindung benötigt. Dazu habe ich den Router so konfiguriert, dass er auf <a href="http://wiki.ubuntuusers.de/Wake_on_LAN">Wake-On-Lan Pakete</a> reagiert.</p>

<p><span id="more-352"></span>
Für MacOSX und Linux habe ich ein kleines Python Script gebastelt, dass ein <i>MagicPaket</i> sendet und so den Router aufweckt (der merkwürdig aussehende String in der letzten Zeile des Skriptes ist die Mac-Adresse des zu weckenden Rechners).</p>

<div><pre class="brush:python">
    #!/usr/bin/env python
    import socket
    s=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.sendto('\xff'*6+'\x01\x40\x24\x2b\x12\xf7'*16, ('192.168.2.2', 80))
</pre></div>

<p>Unter Linux das Skript einfach <a href="http://wiki.ubuntuusers.de/Autostart">per Autostart ausführen</a>. Unter MacOSX könnte man das Skript einfach zu den Login-Items hinzufügen, um es bei jedem Anmelden auszuführen.</p>

<p><a href="http://blog.kips-world.de/wp-content/uploads/2010/06/login_items_macosx.PNG"><img src="http://blog.kips-world.de/thumb.php?file=http://blog.kips-world.de/wp-content/uploads/2010/06/login_items_macosx.PNG" alt="Login Items MacOSX" /></a></p>

<p>Allerdings habe ich unter MacOSX einen etwas anderen Usecase. Ich schalte den Rechner praktisch nie aus, sondern versetze ihn nur in den SleepModus. Deshalb muss ich das Skript immer dann ausführen, wenn der Rechner aus dem SleepModus wieder aufwacht. Dazu nutze ich das kleine Tool <a href="http://www.bernhard-baehr.de/">SleepWatcher</a>. SleepWatcher kann Skripte beim Aufwachen und Schlafengehen von MacOSX ausführen.</p>

<p>Bleibt die Windows-Dose. Auch hier hat der Usecase eine kleine Besonderheit, denn das WOL-Paket muss über WLAN gesendet werden das erst einige Sekunden nach dem Login verfügbar ist. Außerdem muss der Windows-Rechner nach dem Starten des Routers dazu gebracht werden sich vom DHCP Server eine neue IP zu holen.</p>

<p>Zum Senden des MagicPackets habe ich das kleine Tool <a href="http://www.matcode.com/wol.htm">MC-WOL</a> heruntergeladen. Dabei handelt es sich um ein Kommandozeilenprogramm, dass als Parameter einfach nur die MacAdresse des zu weckenden Rechners bekommt. Das ganze habe ich in eine Batch-Datei verpackt:</p>

<p><pre class="brush:bash">
ping localhost -n 15 > NULL
c:\mc-wol.exe 01:40:24:2b:12:f7
ping localhost -n 60 > NULL
ipconfig /renew
</pre></p>

<p>Die beiden Ping Befehle sind ein kleiner Hack. Windows Batch Dateien kennen keinen &#8220;sleep&#8221;-Befehl. Ein Ping dauert jedoch genau eine Sekunde. Wenn man nun 15mal <i>ins leere Pingt</i>, hat man effektiv einen Sleep von 15 Sekunden. Die ersten 15s warten sind zum aktivieren der WLAN-Verbindung, dann sendet die Batch das MagicPaket, wartet wiederum 60s (bis der Router hochgefahren ist) und holt sich dannach eine neue IP.</p>

<p>Von dieser Batch Datei einfach noch eine Verknüpfung erstellen und in den Autostart Ordner verschieben. Der Verknüpfung kann man nun noch sagen, dass sie minimiert starten soll und den Benutzer so nicht stört (geht über die Eigenschaften der Verknüpfung).</p>

<p><a href="http://blog.kips-world.de/wp-content/uploads/2010/06/wol_3.png"><img src="http://blog.kips-world.de/wp-content/uploads/2010/06/wol_3.png" alt="WakeOnLan Windows" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.dennis.io/wakeonlan-beim-startenaufwachen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bloggen mit Textmate</title>
		<link>http://blog.dennis.io/bloggen-mit-textmate/</link>
		<comments>http://blog.dennis.io/bloggen-mit-textmate/#comments</comments>
		<pubDate>Sat, 12 Jun 2010 00:14:07 +0000</pubDate>
		<dc:creator>dennis</dc:creator>
				<category><![CDATA[apple]]></category>
		<category><![CDATA[mac osx]]></category>
		<category><![CDATA[editor]]></category>
		<category><![CDATA[osx]]></category>
		<category><![CDATA[textmate]]></category>

		<guid isPermaLink="false">http://blog.kips-world.de/?p=325</guid>
		<description><![CDATA[Ich habe vor einigen Wochen Textmate für mich entdeckt. Das ist wirklich eines der besten Tools für den Mac, ich weiß nicht wie ich die ganze Zeit ohne diesen genialen Editor ausgekommen bin. Die wohl größte Stärke von Textmate ist seine Anpassbarkeit und die Möglichkeit die Funktionen des Editors über die so genannten Bundles fast [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://blog.kips-world.de/wp-content/uploads/2010/06/textmate_logo.png" alt="Textmate Logo" /></p>

<p>Ich habe vor einigen Wochen <a href="http://macromates.com/" title="Textmate">Textmate</a> für mich entdeckt. Das ist wirklich eines der besten Tools für den Mac, ich weiß nicht wie ich die ganze Zeit ohne diesen genialen Editor ausgekommen bin.</p>

<p>Die wohl größte Stärke von <a href="http://macromates.com/" title="Textmate">Textmate</a> ist seine Anpassbarkeit und die Möglichkeit die Funktionen des Editors über die so genannten Bundles fast beliebig zu erweitern. Zum Beispiel gibt es für Textmate auch ein Blogging-Bundle, mit dem ich gerade diesen Blog-Eintrag schreibe. Das Bundle unterstützt sogar das Hochladen von Bildern direkt über Textmate. Dazu ziehe ich das Bild vom Finder einfach in den Texteditor an die passende Stelle, vergebe einen Titel und den Rest übernimmt Textmate.</p>

<p><a href="http://blog.kips-world.de/wp-content/uploads/2010/06/bloggen_mit_textmate1.PNG"><img src="http://blog.kips-world.de/thumb.php?file=http://blog.kips-world.de/wp-content/uploads/2010/06/bloggen_mit_textmate1.PNG" alt="Bloggen mit Textmate" /></a></p>

<p>Einziger Wermutstropfen: Die Bilder werden von Textmate nur hochgeladen, es werden leider nicht automatisch Thumbnails erstellt. Aber Moment, ich habe doch gerade Textmate dafür gelobt wie flexibel es ist, also einfach selbst eine Lösung dafür basteln.</p>

<p><span id="more-325"></span>
Ein Weg wäre das Blogging Bundle zu ändern und diese Funkion nachzurüsten, allerdings implementiert Textmate die Metablog API um mit möglichst vielen Blogplattformen kompatibel zu sein und ein Eingriff an dieser Stelle würde damit wohl brechen.</p>

<p><a href="http://blog.kips-world.de/wp-content/uploads/2010/06/bundle_editor.PNG"><img src="http://blog.kips-world.de/thumb.php?file=http://blog.kips-world.de/wp-content/uploads/2010/06/bundle_editor.PNG" alt="Bundle Editor" /></a></p>

<p>Deshalb habe ich einen anderen Ansatz gewählt. Zunächst habe ich mir im Blogging Bundle von Textmate ein neues <code>Command</code> angelegt (Bundles > Bundle Editor > Show Bundle Editor). Dieses Command wende ich auf eingefügte Bilder an. Es ist ein kleines Ruby-Script, welches den Code für das eingefügte Bild umformatiert und einen Link auf ein PHP Script erzeugt. Diesem PHP Script übergebe ich über einen Parameter die URL des Original Bildes (der komplette Code hierfür wird automatisch durch das Command erzeugt). Das PHP Script schaut nun auf dem Server ob für das Bild schon ein Thumbnail existiert. Falls ja, gibt das Script einfach das Thumbnail aus. Falls nein, erzeugt das Script ein Thumbnail in passender Größe und gibt dieses anschließend aus. D.h. der gesamte Ablauf zum Einfügen des Bildes inklusive Thumbnail sieht folgendermaßen aus:</p>

<ol>
<li>Bild vom Finder in Textmate ziehen</li>
<li>Command aufrufen (STRG+Q bei mir)</li>
<li>Fertig!</li>
</ol>

<p>Diese Methode hat auch ein paar Nachteile, aber hier erstmal der Code für das Command (die anderen Einstellungen für das Command bitte aus dem Screenshot entnehmen):</p>

<div><pre class="brush:ruby">
#!/usr/bin/ruby

txt = STDIN.read
md = /\!\[([\w\s]*)\]\((http:[\/\.\w-]*)/.match(txt)
if (md != nil)
    puts "[![#{md[1]}](http://blog.kips-world.de/thumb.php?file=#{md[2]})](#{md[2]})"
end
</pre></div>

<p><i>Achtung:</i> Ich benutze Markdown zum schreiben von Blogposts. Das Script funktioniert in dieser Form nur mit Markdown, nicht mit HTML!</p>

<p>Und hier noch der Quellcode des PHP Scripts auf dem Server:</p>

<div><pre class="brush:php">
    $path = dirname(__FILE__).'/wp-content/uploads';

    $f = $_GET['file'];
    $name = basename($f);
    $dir = dirname($f);
    preg_match('/.*\/([a-zA-Z0-9]*)\/([a-zA-Z0-9]*)/', $dir, $s);
    $p = $path.'/'.$s[1].'/'.$s[2];

    preg_match('/(.*)\.([a-zA-Z]{2,3})/', $name, $res);
    
    $thumb = $res[1].'_thumb.'.$res[2];
    $_thumb = $p.'/'.$thumb;

    if (!file_exists($_thumb)) {
        
        copy($p.'/'.$name, $_thumb);
        // this needs imagemagick!
        shell_exec('/usr/bin/convert '.$_thumb.' -thumbnail \'600\' '.$_thumb);     
    }
    header('Last-Modified: '.date('r'));
    header('Content-Type: image/'.strtolower($res[2]));
    readfile($_thumb);
</pre></div>

<p>Jetzt zu den Nachteilen. Ich erstelle bei dieser Methode die Thumbnails <code>an WordPress vorbei</code>. D.h. WordPress weiß nichts über diese Thumbnails und man kann sie deshalb auch nicht über WordPress verwalten. Wenn man jedoch etwas mehr Mühe in das Script zur Generierung der Thumbs steckt bin ich mir sicher, dass man das erreichen kann (einfach die entsprechenden Funktionen von WP zur Erstellung von Thumbs hijacken).</p>

<p>Vorteile hat diese Methode aber auch. Sollte man mal das Layout seines Blogs ändern (und deshalb vllt. eine andere Thumbnail-Größe benötigen), muss man nur das Thumbnail Script entsprechen anpassen und alle Thumbnails auf dem Server löschen. Sobald jemand auf die Thumbnails zugreift werden sie dann automatisch neu erstellt &#8211; in der richtigen Größe.</p>

<p>Hier noch ein paar nützliche Textmate Ressourcen:</p>

<ul>
<li><a href="http://dl.kips-world.de/misc/TextMate%20(Web)%20Developer's%20Cheat%20Sheet.pdf">Developer Cheat Sheet</a> mit den wichtigsten Tastatur-Shortcuts</li>
<li><a href="http://macromates.com/screencasts">Offizielle Textmate Screencasts</a> (sehr Informativ!)</li>
</ul>

<p>(werde im Laufe der Zeit noch ein paar mehr hinzufügen)</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.dennis.io/bloggen-mit-textmate/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ubuntu 10.04 in VMWare Fusion</title>
		<link>http://blog.dennis.io/ubuntu-10-04-in-vmware/</link>
		<comments>http://blog.dennis.io/ubuntu-10-04-in-vmware/#comments</comments>
		<pubDate>Thu, 10 Jun 2010 21:43:53 +0000</pubDate>
		<dc:creator>dennis</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[mac osx]]></category>
		<category><![CDATA[10.04]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[vmware]]></category>

		<guid isPermaLink="false">http://blog.kips-world.de/?p=290</guid>
		<description><![CDATA[Nachdem ich vor ein paar Tagen ein Update meiner Ubuntu-VM auf 10.04 gemacht hatte konnte ich mich nicht mehr einloggen. Das Problem: Im Login-Screen von GDM funktionierte keine Tastatur mehr. Maus kein Problem, aber ohne Tastatur kann man halt schlecht ein Passwort eingeben. Das Problem ist ein falscher Eintrag in der Datei /etc/default/console-setup. Nach der [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://blog.kips-world.de/wp-content/uploads/2010/06/vmware_fusion.png" alt="Vmware Fusion" /></p>

<p>Nachdem ich vor ein paar Tagen ein Update meiner Ubuntu-VM auf 10.04 gemacht hatte konnte ich mich nicht mehr einloggen.
Das Problem: Im Login-Screen von GDM funktionierte keine Tastatur mehr. Maus kein Problem, aber ohne Tastatur kann man halt schlecht ein Passwort eingeben.</p>

<p><span id="more-290"></span>
Das Problem ist ein falscher Eintrag in der Datei /etc/default/console-setup. Nach der Ubuntu 10.04 Installation findet man dort unter anderem folgende Einträge:</p>

<p><pre class="brush:bash">
XKBMODEL=”SKIP”
XKBLAYOUT=”us”
XKBVARIANT=”U.S. English”
XKBOPTIONS=”"
</pre></p>

<p><a href="http://blog.kips-world.de/wp-content/uploads/2010/06/3.PNG"><img src="http://blog.kips-world.de/thumb.php?file=http://blog.kips-world.de/wp-content/uploads/2010/06/3.PNG" alt="3" /></a></p>

<p>Die Einträge müssen wie folgt angepasst werden damit die Tastatur unter VMWare(Fusion) wieder läuft:</p>

<p><pre class="brush:bash">
XKBMODEL=”pc105″
XKBLAYOUT=”us”
XKBVARIANT=”"
XKBOPTIONS=”"
</pre></p>

<p>Bleibt die Frage &#8211; wie an die Datei herankommen wenn man sich nicht einloggen kann? Zu diesem Problem gibt es zwei Lösungen:</p>

<ol>
<li><p>Möglichkeit: Beim Booten in Grub den Konsolen-Login auswählen &#8211; dort funktioniert die Tastatur einwandfrei.</p></li>
<li><p>Möglichkeit: Das <i>on-screen Keyboard</i> zum einloggen benutzen. Dazu klickt man im Login-Screen auf das Symbol für die &#8220;Universal Access Preferences&#8221; (im Standard 10.04 Theme das kleine Männchen mit dem Kreis drumherum) und aktiviert im Folgedialog die Option &#8220;Use on-screen keyboard&#8221;. Leider kann es nun durch einen anderen Bug passieren, dass das Keyboard zwar kurz zu sehen ist aber sofort wieder verschwindet. In diesem Fall die VM einfach einmal neubooten, dann sollte das Keyboard sichtbar sein.</p></li>
</ol>

<p><a href="http://blog.kips-world.de/wp-content/uploads/2010/06/1.PNG"><img src="http://blog.kips-world.de/thumb.php?file=http://blog.kips-world.de/wp-content/uploads/2010/06/1.PNG" alt="1" /></a>
<a href="http://blog.kips-world.de/wp-content/uploads/2010/06/2.PNG"><img src="http://blog.kips-world.de/thumb.php?file=http://blog.kips-world.de/wp-content/uploads/2010/06/2.PNG" alt="2" /></a></p>

<p>Nach dem einloggen die oben genannte Datei ändern und neustarten &#8211; dann sollte alles wieder wie gewohnt funktionieren.
Ich hatte übrigens noch einen weiteren Bug beim Booten. Bei mir erschien der LoginManager für 1-2 Sekunden, dannach wurde der Bildschirm aber wieder schwarz. Hier hilft es beim Booten einfach mal &#8220;F2&#8243; zu drücken und damit die Bootkonsole zu aktivieren.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.dennis.io/ubuntu-10-04-in-vmware/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Serverumzug</title>
		<link>http://blog.dennis.io/serverumzug/</link>
		<comments>http://blog.dennis.io/serverumzug/#comments</comments>
		<pubDate>Mon, 22 Mar 2010 02:14:03 +0000</pubDate>
		<dc:creator>dennis</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[dovecot]]></category>
		<category><![CDATA[ldap]]></category>
		<category><![CDATA[postfix]]></category>

		<guid isPermaLink="false">http://blog.kips-world.de/?p=270</guid>
		<description><![CDATA[Ich habe seit Jahren zusammen mit einem Kumpel bei der Firma Hetzner einen dedizierten Root-Server. Auf diesem Server laufen diverse Webseiten (auch dieser Blog), ein paar Foren, ein paar Teamspeak-Server, ein SVN Repository und am allerwichtigsten: mein gesamter Email-Verkehr wird über diesen Server abgewickelt. Mein Kumpel möchte jetzt allerdings einiges an seiner Infrastruktur ändern und [...]]]></description>
			<content:encoded><![CDATA[<p>Ich habe seit Jahren zusammen mit einem Kumpel bei der Firma Hetzner einen dedizierten Root-Server. Auf diesem Server laufen diverse Webseiten (auch dieser Blog), ein paar Foren, ein paar Teamspeak-Server, ein SVN Repository und am allerwichtigsten: mein gesamter Email-Verkehr wird über diesen Server abgewickelt. Mein Kumpel möchte jetzt allerdings einiges an seiner Infrastruktur ändern und benötigt den Server deshalb in Zukunft nicht mehr. Da mir ein dedizierter Root-Server alleine etwas zu teuer ist, werde ich auf einen vServer umsteigen. Dieser hat natürlich nicht die Power wie ein eigener Server, aber da ich ihn dann nur noch alleine nutze wird das schon langen. Das kostenlose Hosting einiger Webseiten für ein paar Freunde werde ich dann allerdings einstellen müssen :/</p>

<p>Nach ein bisschen Recherche im Web habe ich mich für das <a href="http://www.hosteurope.de/produkt/Virtual-Server-Linux-L">Paket VS Linux L 4.0 von HostEurope</a> entschieden. Eine Alternative wäre noch der <a href="http://www.server4you.de/vserver/vserver-details.php?products=0">vServer Pro X4 von Server4You</a> gewesen. Letzterer ist bei vergleichbarer Leistung deutlich billiger, allerdings verbinde ich mit Server4You nur negative Nachrichten aus deren Anfangszeiten. Mag sein, dass sie mittlerweile dazugelernt haben, das negative Bild hat sich bei mir aber zu sehr eingebrannt. Meine Domains werde ich weiter über den DomainRobot von Hetzner verwalten, da gibt es für mich keine Alternative.</p>

<p>Demnächst steht also ein Umzug aller Dienste und Daten an. Nun habe ich mir überlegt, wenn ich schon alles umziehen und neumachen muss, dann kann ich das auch richtig machen. Deshalb werde ich im gleichen Schritt auch von MySQL auf LDAP als Datenbackend umsteigen. Natürlich ist ein LDAP Server für einen so kleinen Server mit rund 10 Domains und 20 Email-Konten etwas oversized, aber es ist die sauberste Lösung und ausprobieren wollte ich das schon länger mal. Ich habe mir für den neuen Server folgende Struktur überlegt:</p>

<p><a href="http://blog.kips-world.de/wp-content/uploads/2010/03/vserver-plan2.png"><img src="http://blog.kips-world.de/wp-content/uploads/2010/03/vserver-plan2-500x250.png" alt="vserver-plan" title="vserver-plan" width="500" height="250" class="aligncenter size-thumbnail wp-image-279" /></a></p>

<p>Postfix als MTA mit Amavis, Spamassassin und PolicyD als Content Filter &#8211; so bleibt das Email-Postfach sauber! Zum Senden/Relayen von Mails ist natürlich eine Authentifizierung erforderlich. Dazu wird Postfix über Cyrus-SASL an den LDAP angebunden. Darüberhinaus benutzt Postfix den LDAP um Domain/Mailbox Lookups zu machen (also sicherzustellen, dass die Emailadressen an die Mails gesendet werden sollen auch auf dem Server existieren).</p>

<p>Dovecot habe ich seit etwas mehr als einem Jahr im produktiven Einsatz und bin damit sehr zufrieden. Dovecot unterstützt eine direkte Anbindung an LDAP (zur Authentifizierung). Sowohl Postfix als auch Dovecot werden für <a href="http://de.wikipedia.org/wiki/Mail_User_Agent">MUAs</a> nur per SSL/TLS erreichbar sein. Als Webmail Applikation bleibe ich bei <a href="http://roundcube.net/">RoundCube</a> &#8211; ich find den Web2.0 Style von RoundCube einfach hübscher als <a href="http://squirrelmail.org/">SquirrelMail</a>.</p>

<p>Auch den Apache möchte ich an das LDAP Backend anbinden. Sowohl zur Verwaltung von (Sub-)Domains als auch zur Authentifizierung beim SVN und WebDAV Dienst (ob das überhaupt möglich ist weiß ich aber noch nicht).</p>

<p>Zu guter letzt möchte ich meinen Router hier Zuhause als BackupMX konfigurieren. Falls der vServer einmal ausfällt soll unser heimische Router die Mails entgegennehmen. Dazu muss er natürlich auf die Domaindaten zugreifen können. Deshalb muss auf dem Router ein LDAP-Replica-Server laufen der alle Daten vorhält. Auch müssen hier alle Antispam und Antiviren Maßnahmen installiert sein, denn Spammer benutzen gerne den BackupMX um ihren Müll abzuladen. Inwieweit dies umsetzbar ist muss ich ebenfalls noch ausprobieren.</p>

<p>Ich stelle das ganze Vorhaben hier deshalb so ausführlich vor, weil ich mir vorgenommen habe zu allen Diensten und Konfigurationen hier im Blog Tutorials zu veröffentlichen. Falls ich diesem Vorsatz nachkommem kann ensteht hier nicht nur eine Dokumentation für mich selbst, sondern hoffentlich auch ein nützliches Nachschlagewerk für andere.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.dennis.io/serverumzug/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

