<?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>PINC-Blog &#187; Java</title>
	<atom:link href="http://www.pincservices.de/wordpress/tag/java/feed" rel="self" type="application/rss+xml" />
	<link>http://www.pincservices.de/wordpress</link>
	<description>yet another developer blog</description>
	<lastBuildDate>Sat, 10 Sep 2011 07:53:09 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>Joda &#8211; &#8220;Bis 900 Jahre, wirst aussehen du nicht gut!&#8221;</title>
		<link>http://www.pincservices.de/wordpress/joda-bis-900-jahre-wirst-aussehen-du-nicht-gut</link>
		<comments>http://www.pincservices.de/wordpress/joda-bis-900-jahre-wirst-aussehen-du-nicht-gut#comments</comments>
		<pubDate>Tue, 15 Dec 2009 09:45:34 +0000</pubDate>
		<dc:creator>Rob</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[date api]]></category>
		<category><![CDATA[joda]]></category>

		<guid isPermaLink="false">http://www.pincservices.de/wordpress/?p=370</guid>
		<description><![CDATA[Mit diesen Worten hat Yoda in Starwars nicht nur eine der traurigsten Szenen aufgelockert, sondern auch gleich &#8211; unbeabsichtigt &#8211; ein Grundproblem der Javawelt adressiert. Die API für die Zeitverwaltung. Wann wenn nicht jetzt? Beim Stöbern in Quellcode bin ich letztens wiedermal über eine lustige Zeile gestoßen: ... System.currentTimeInMillis() //we can get the time in [...]]]></description>
			<content:encoded><![CDATA[<p>Mit diesen Worten hat Yoda in Starwars nicht nur eine der traurigsten Szenen aufgelockert, sondern auch gleich &#8211; unbeabsichtigt &#8211; ein Grundproblem der Javawelt adressiert. Die API für die Zeitverwaltung.</p>
<h3>Wann wenn nicht jetzt?</h3>
<p>Beim Stöbern in Quellcode bin ich letztens wiedermal über eine lustige Zeile gestoßen:</p>
<pre class="brush: plain;">
...
System.currentTimeInMillis() //we can get the time in milliseconds after 1 Jan 1970 at 0:00:00am GMT
...
</pre>
<p>Auf den ersten Blick harmlos. Was soll da schon passieren? Ich will die Frage umformulieren: Was passiert danach? Mit dem Wert wird in der Regel angefangen zu arbeiten. D.h. Tage werden hinzugefügt, abgezogen um z.B. Startzeitpunkte zu ermitteln. Dabei wurde in dem Code, den ich gesehen habe in etwa folgendes gemacht:</p>
<pre class="brush: plain;">
final long now = System.currentTimeInMillis();
final long oneDay = 1000 * 60 * 60 * 24;
final long tomorrow = now + oneDay;
...
</pre>
<p>Sieht immer noch alles harmlos aus? Dann weiter &#8230;</p>
<h3>Ein Tag hat 24 Stunden</h3>
<p>An einer anderen Stelle wurde ein Vergleich zweier Daten durchgeführt. Hier die anonymisierte Fassung:</p>
<pre class="brush: plain;">
final long oneDay = 1000 * 60 * 60 * 24;

final Calendar calendar = Calendar.getInstance();
calendar.set(2009, 9, 24, 10, 0);
final long summerTime = calendar.getTimeInMillis();

final Calendar comparisonCalendar = Calendar.getInstance();
comparisonCalendar.set(2009, 9, 26, 10, 0);
final long winterTime = comparisonCalendar.getTimeInMillis();

final long difference = winterTime - summerTime;

if (difference == 2 * oneDay) {
    ...
}
</pre>
<p>Immer noch harmlos? Der ein oder andere wird jetzt sagen: klar. Leider steckt der Teufel im Detail. Was meistens vernachlässigt wird ist die europäische (Un)Sitte zwischen Sommer- und Winterzeit zu wechseln oder auch ganz allgemein alle 4 Jahre mal einen Tag im Februar mehr einzuplanen. Hier muss sich dieser Ansatz leider geschlagen geben.</p>
<p>Ich muss mich an dieser Stelle entschuldigen, denn ich habe den Code bereits so abgeändert, dass das Problem der Sommer- und Winterzeit offensichtlich wird. Der Originalcode sieht natürlich etwas anders aus. Aber nun sollte definitiv ersichtlich werden, warum das nicht funktionieren kann. Hier wird mit festen Zeitintervallen (<code>oneDay</code>) gearbeitet. Leider hat der Tag zum Zeitwechsel nicht 24, sondern entweder 23 oder 25 Stunden.</p>
<p>Geht man mit Java-Hausmitteln an dieses Problem landet man dann aber auch schnell in Code-Schnippseln wie dem Folgenden:</p>
<pre class="brush: plain;">
...
Calendar calendar = Calendar.getInstance();
Date now = calendar.getTime();
calendar.add(Calendar.HOUR_OF_DAY, 1);

...
</pre>
<p>oder die Alternative für den Vergleichscode:</p>
<pre class="brush: plain;">
...
Calendar calendar = Calendar.getInstance();
calendar.setTime(2009, 9, 24, 10, 0);
calendar.add(Calendar.HOUR_OF_DAY, 2);

Calendar comparisonCalendar = Calendar.getInstance();
comparisonCalendar.setTime(2009, 9, 26, 10, 0);
if (calendar.getTimeInMillis() == comparisonCalendar.getTimeInMillis()) {
...
</pre>
<p>Damit löst man zwar das Problem mit der Zeitumstellung, aber auf Dauer ist schön was anderes, denn ein weiterer Schwachpunkt der API, aus meiner Sicht, ist die schlechte Lesbarkeit. Denn wer sieht schon auf den ersten Blick, dass hier nicht der September, sondern der Oktober gemeint ist. Ja, man kann auch mit den <code>Calendar</code>-Konstanten arbeiten, aber auch das führt eher zu unnötig langen Codezeilen.</p>
<h3>&#8230; einer, der der Macht das Gleichgewicht bringen wird &#8230;</h3>
<p>Eine elegante Lösung hierfür bietet &#8211; nein nicht Skywalker, sondern &#8211; die <a href="http://joda-time.sourceforge.net/">Joda-Bibliothek</a>. Diese erlaubt es das Millisecond-Massaker zu umgehen und die Schwächen der Standard-API zu minimieren. So sieht der Code von oben mit Joda etwa so aus:</p>
<pre class="brush: plain;">
...
DateTime dt = new DateTime();
DateTime oneDayLater = dt.plusDays(1);
DateTime oneDayEarlier = dt.minusDays(1);
...
</pre>
<p>Auch Vergleiche wirken wesentlich angenehmer:</p>
<pre class="brush: plain;">
final DateTime now = new DateTime();
final DateTime before = now.minusDays(100);
final Days days = Days.daysBetween(before, now);
if (days.getDays() == 2) {
...
</pre>
<h3>&#8220;Schneller, leichter, verführerischer&#8221;</h3>
<p>Auch wenn das nur ein erster Blick auf Joda war, zeigt sich hier schon die Eleganz und Mächtigkeit dieser Bibliothek. Wer sich nicht scheut ein wenig englisch zu lesen, sei für weitere Informationen auf das IBM-Tutorial <a href="http://www.ibm.com/developerworks/java/library/j-jodatime.html" target="_blank">Joda-Time</a> und die Website <a href="http://joda-time.sourceforge.net" target="_blank">http://joda-time.sourceforge.net</a> selbst verwiesen.</p>
<p>Ansonsten, sehen wir uns in 900 Jahren um Mitternacht <img src='http://www.pincservices.de/wordpress/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<pre class="brush: plain;">
final LocalDate localDate = new LocalDate();
final DateTime then = localDate.toDateMidnight().toDateTime().plusYears(900);
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.pincservices.de/wordpress/joda-bis-900-jahre-wirst-aussehen-du-nicht-gut/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Webapps become wicket &#8230;</title>
		<link>http://www.pincservices.de/wordpress/webapps-become-wicket</link>
		<comments>http://www.pincservices.de/wordpress/webapps-become-wicket#comments</comments>
		<pubDate>Sat, 26 Sep 2009 00:59:55 +0000</pubDate>
		<dc:creator>Rob</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Webentwicklung]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[wicket]]></category>

		<guid isPermaLink="false">http://www.pincservices.de/wordpress/?p=247</guid>
		<description><![CDATA[Im Allgemeinen sprießen Webframeworks wie Pilze aus dem Boden. Mal mehr und mal weniger erfolgreich. Allerdings haben die meisten immer den gleichen MVC-Ansatz. Daten werden im Model vorgehalten, der Controller kümmert sich um die Bereitstellung der Objekte und der Navigation und das View &#8220;holt&#8221; sich alles was es braucht aus dem Kontext. D.h. man hat [...]]]></description>
			<content:encoded><![CDATA[<p>Im Allgemeinen sprießen Webframeworks wie Pilze aus dem Boden. Mal mehr und mal weniger erfolgreich. Allerdings haben die meisten immer den gleichen MVC-Ansatz. Daten werden im Model vorgehalten, der Controller kümmert sich um die Bereitstellung der Objekte und der Navigation und das View &#8220;holt&#8221; sich alles was es braucht aus dem Kontext. D.h. man hat häufig eine Mischung aus HTML und einer expliziten Expression Language im View (z.B. JSTL).<br />
Der große Nachteil bei dieser Form von Aufteilung ist, dass man beim Testen häufig auf verschiedene Frameworks zurückgreifen muss um die Korrektheit der Anzeige zu gewährleisten bzw. stark auf manuelles Testen angewiesen ist. Im Speziellen sei hier die Problematik von Text-Lokalisierung erwähnt, die jedem Entwickler im Laufe seiner Arbeit schonmal &#8220;auf die Füße gefallen&#8221; sein wird.</p>
<p>Einen etwas anderen Ansatz verfolgt an dieser Stelle das Framework <a href="http://wicket.apache.org">Wicket</a>. Hier wird bewusst auf eine explizite Expression Language verzichtet &#8211; soweit ich sehen kann. Alle Referenzen zwischen Controller und View werden über eine Wicket-Id-Tag (<code>&lt;span wicket:id="myMessage"&gt;&lt;/span&gt;</code>) aufgelöst. Damit steht zwar der Controller in der Pflicht alle Inhalte entsprechend umfangreicher aufzubereiten (z.B. explizite Änderungs-Propagierung), aber diese Vorgehensweise hat den elementaren Vorteil, dass Seiten wesentlich einfacher auch mit z.B. Junit-Tests geprüft werden können.</p>
<p>Es wäre alles zu schön um wahr zu sein, wenn es nicht schon auf den/meinen ersten Blick ein kleines Problem gäbe. Natürlich geht Wicket von einem MVC-Ansatz aus und benötigt damit HTML-Dateien zum Rendern. Leider wird standardmäßig davon ausgegangen, dass die HTML-Dateien im gleichen Verzeichnis liegen wie die entsprechende Klasse.<br />
<b-quote><i><br />
&#8220;First we need to create a web page. Wicket has a WebPage class suited for this task. All webpages need to be subclasses of WebPage. Another requirement is that the actual HTML file and the class name are equal: Index.html and Index, IndexPage.html and IndexPage or HelloWorld.html and HelloWorld. They also need to be in the same place on the classpath. The best way to develop is to put them in the same directory. This might seem strange in the beginning, especially when you are accustomed to separate html files and java files. However, since all pages are actually just components, it makes perfect sense in terms of reusability.&#8221;<br />
</i><br />
(siehe hierzu <a href="http://cwiki.apache.org/WICKET/newuserguide.html#Newuserguide-TheHTML">http://cwiki.apache.org/WICKET/newuserguide.html#Newuserguide-TheHTML</a>)<br />
</b-quote></p>
<p>Für jeden Webentwickler, der es gewohnt ist, dass HTML- respektive JSP(X)-Dateien gefälligst weit weg von den Klassen zu liegen haben, eine Umstellung die nur leidlich zu ertragen ist.<br />
Zum Glück haben die Wicket-Entwickler hier aber ein Einsehen und bieten in der Referenz-Dokumentation auch gleich mehrere <a href="http://cwiki.apache.org/WICKET/control-where-html-files-are-loaded-from.html">Lösungen</a> an, wobei aus meiner Sicht, die Maven-Lösung zu empfehlen ist, da sie versionsunabhängig ist.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pincservices.de/wordpress/webapps-become-wicket/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Projektseite &#8220;FinanzMauMau&#8221;</title>
		<link>http://www.pincservices.de/wordpress/projektseite-finanzmaumau</link>
		<comments>http://www.pincservices.de/wordpress/projektseite-finanzmaumau#comments</comments>
		<pubDate>Fri, 21 Mar 2008 20:13:43 +0000</pubDate>
		<dc:creator>Rob</dc:creator>
				<category><![CDATA[Allgemein]]></category>
		<category><![CDATA[Projekte]]></category>
		<category><![CDATA[Andrea Schmidt]]></category>
		<category><![CDATA[FinanzMauMau]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JMonkey]]></category>

		<guid isPermaLink="false">http://www.pincservices.de/wordpress/projektseite-finanzmaumau</guid>
		<description><![CDATA[Das Projekt &#8220;FinanzMauMau&#8221; hat hier eine eigene kleine Projektseite erhalten. Dort wird das Spiel in seinen Grundzügen und einige Erweiterungsmöglichkeiten vorgestellt. Außerdem kann man dort diverse Screenshots sehen.]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.pincservices.de/wordpress/projekte/finanzmaumau"><img src="http://www.pincservices.de/wordpress/wp-content/uploads/2008/03/karten1.thumbnail.png" alt="Karten 1" align="left" border="0" /></a> Das Projekt &#8220;FinanzMauMau&#8221; hat <a href="http://www.pincservices.de/wordpress/projekte/finanzmaumau">hier</a> eine eigene kleine Projektseite erhalten. Dort wird das Spiel in seinen Grundzügen und einige Erweiterungsmöglichkeiten vorgestellt. Außerdem kann man dort diverse Screenshots sehen.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pincservices.de/wordpress/projektseite-finanzmaumau/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

