<?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>Triona Weblog</title>
	<atom:link href="http://blog.triona.de/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.triona.de</link>
	<description>Software Development and much more</description>
	<lastBuildDate>Tue, 10 Apr 2012 15:32:43 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Excel VBA Entwicklung (Teil 2): Allgemeines</title>
		<link>http://blog.triona.de/development/excel-vba-entwicklung-teil-2-allgemeines.html</link>
		<comments>http://blog.triona.de/development/excel-vba-entwicklung-teil-2-allgemeines.html#comments</comments>
		<pubDate>Tue, 10 Apr 2012 15:32:43 +0000</pubDate>
		<dc:creator>Thomas Wehrspann</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Addin]]></category>
		<category><![CDATA[Excel]]></category>
		<category><![CDATA[Makro]]></category>
		<category><![CDATA[VBA]]></category>
		<category><![CDATA[VBE]]></category>

		<guid isPermaLink="false">http://blog.triona.de/?p=1263</guid>
		<description><![CDATA[Die im letzten Artikel vorgestellte Aufzeichnungsfunktion für Makros reicht zur Automatisierung einfacher Aufgaben aus. Will man komplexere Funktionen und vielleicht eine Benutzeroberfläche hinzufügen, muss man in die Programmierung mit VBA einsteigen. Visual Basic Editor Programmieren tut man im mitgelieferten Visual Basic Editor (VBE). Der VBE lässt sich über die Tastenkombination ALT+F11 oder aus dem Entwicklungstab des [...]]]></description>
			<content:encoded><![CDATA[<p>Die im letzten Artikel vorgestellte Aufzeichnungsfunktion für Makros reicht zur Automatisierung einfacher Aufgaben aus. Will man komplexere Funktionen und vielleicht eine Benutzeroberfläche hinzufügen, muss man in die Programmierung mit VBA einsteigen.</p>
<h2>Visual Basic Editor</h2>
<p>Programmieren tut man im mitgelieferten Visual Basic Editor (VBE). Der VBE lässt sich über die Tastenkombination ALT+F11 oder aus dem Entwicklungstab des Ribbon starten. Wie das Entwicklungstab eingeblendet wird hatten wir im letzten Artikel besprochen.</p>
<p>Der Funktionsumfang von VBE ist eher rudimentär. Besserung gibt es in Form des Addons MZTools. Dieses liefert viele vermisste Funktionen nach und ist zudem kostenfrei erhältlich. Wichtig: die Version 3.0 wählen.</p>
<p>Eine Funktion die VBE bietet, die man aber wegen ihres aufdringlichen Verhaltens besser abschaltet ist die automatische Fehlerprüfung nach Abschluss eine Zeile. Verlässt man eine Zeile, die ungewollt oder absichtlich noch Fehler enthält, wird man umgehend mit einer Fehlermeldung in Form eines Hinweisfensters bestraft. Diese Funktion kann man getrost abschalten, fehlerhafte Zeilen werden immer noch deutlich sichtbar in rot dargestellt, jedoch wird der Arbeitsfluss nicht mehr unterbrochen.</p>
<h2>Teamarbeit</h2>
<p>Plant man mit mehreren Leuten im Team zu arbeiten, wird man schnell feststellen, dass das so nicht vorgesehen ist. VBE unsterstützt grundsätzlich nur eine Person. Muss man trotzdem mit mehreren Personen an einem Projekt arbeiten, kann man dies mithilfe eines Versionskontrollsystems wie Subversion versuchen. Ich schreibe versuchen, weil auch diese Art des Arbeitens (bzw. Versionskontrollsysteme allgemein) von VBE nicht unterstützt wird. So kann man zwar Exceldateien unter Versionskontrolle stellen, jedoch können diese mit dem Format nichts anfangen und Änderungen von mehreren Personen auch nicht zusammenführen. Man muss die einzelnen Module und Klassen aus VBE heraus ex- und importieren und das Versionskontrollsystem manuell steuern (etwa über TotoiseSVN für Subversion). Das ist aber auf Dauer ein mühseliges und sehr fehleranfälliges Verfahren.</p>
<p>Ein weiteres Addin für den VBE kann hier zumindest Unterstützung anbieten. Mit CodeCleaner kann man den Ex- und Import der Module automatisieren. Das Versionskontrollsystem muss man aber nach wie vor selbst bedienen.</p>
<p>Der Vollständigkeit halber sei erwähnt, dass es auch ein Addin gibt, das auf Teilen von CodeCleaner aufsetzt und auch den SVN Im- und Export übernimmt. Dieses Addin ist aber einerseits auf Subversion ausgelegt und hat bei mir im Praxiseinsatz nicht überzeugt. Aber beide Addins sind kostenlos und im Quellcode verfügbar, so dass mit etwas VBA-Kenntnissen und Zeit jeder eine eigene Lösung entwickeln kann.</p>
<h2>Struktur und Art</h2>
<p>Exceldateien unterscheiden sich in solche Mit Codemodulen (*.xlsm) und solche Ohne Codemodule (*.xlsx) und Addins (*.xlam). Addins besitzen keine für den Benutzer sichtbaren Tabellen, diese sind allerdings vorhanden und verwendbar, lassen sich nur nicht für den Benutzer darstellen.</p>
<p>Eine Exceldatei besteht aus:</p>
<ul>
<li>Excel-Objekten</li>
<ul>
<li>Arbeitsmappe</li>
<li>Tabellen</li>
</ul>
<li>Formulare</li>
<li>Module</li>
<li>Klassenmodule</li>
</ul>
<p>Code lässt sich in allen Teilen ablegen. Der beste Ort hängt von der Art des Problems und der Form des zu entwickelnden Programms ab.</p>
<p>Grob kann man sagen: Arbeitsmappen/Tabellenspezifischer Code wird im entsprechenden Excel-Objekt abgelegt, GUI-Beschreibungen (mit grafischem Editor) und zugehöriger Code als Formulare. Der Großteil des Codes (insbesondere bei Addins) dürfte jedoch in Modulen hinterlegt werden und bei objektorientierter Programmierung in Klassenmodulen.</p>
<h2>Addins</h2>
<p>Addins dienen dazu Excel um neue Funktionen zu erweitern. Man kann neue Tabellenfunktionen entwickeln, neue Benutzeroberflächen inklusive Ribbon-Einbindung. Es lässt sich auf beinahe jedes Ereignis von Excel reagieren und wenn man will kann man auch komplett die Kontrolle übernehmen und Excel wie seine eigene Anwendung aussehen lassen.</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.triona.de/development/excel-vba-entwicklung-teil-2-allgemeines.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Collections-Überblick</title>
		<link>http://blog.triona.de/development/java/1444.html</link>
		<comments>http://blog.triona.de/development/java/1444.html#comments</comments>
		<pubDate>Tue, 10 Apr 2012 09:58:58 +0000</pubDate>
		<dc:creator>Daniel Holderbaum</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Collections]]></category>
		<category><![CDATA[List]]></category>
		<category><![CDATA[Map]]></category>
		<category><![CDATA[Queue]]></category>
		<category><![CDATA[Set]]></category>
		<category><![CDATA[Stack]]></category>

		<guid isPermaLink="false">http://blog.triona.de/?p=1444</guid>
		<description><![CDATA[Im Zuge der Überarbeitung der Collection-API in Java 1.2 gibt es eine Vielzahl unterschiedlicher Collections. Einen Überblick über die meist-genutzten Collections soll die unten stehende Abbildung verschaffen. Diese listet zu den verschiedenen Implementationen einige Eigenschaften auf, die die Collections voneinander unterscheiden. Bei der ersten Eigenschaft „Typ“ wird ausgesagt welche Interfaces implementiert werden. Damit werden Aussagen [...]]]></description>
			<content:encoded><![CDATA[<p>Im Zuge der Überarbeitung der Collection-API in Java 1.2 gibt es eine Vielzahl unterschiedlicher Collections. Einen Überblick über die meist-genutzten Collections soll die unten stehende Abbildung verschaffen. Diese listet zu den verschiedenen Implementationen einige Eigenschaften auf, die die Collections voneinander unterscheiden.</p>
<p>Bei der ersten Eigenschaft „Typ“ wird ausgesagt welche Interfaces implementiert werden. Damit werden Aussagen darüber gemacht welche Zugriffsmöglichkeiten auf die Elemente möglich sind. Der Typ mit den wenigsten Möglichkeiten ist <em>Set</em>. Hier sind nur Basisoperationen wie <code>add</code>, <code>remove</code> und <code>contains</code> vorhanden. Eine <em>List</em> bietet zudem noch die Möglichkeit, per Indizes Elemente hinzuzufügen, zu löschen oder auszulesen. Methoden wie <code>push</code> und <code>pop</code>, die Zugriff auf die Elemente in einer FIFO-Manier gewähren, sind für den Typ „<em>Stack</em>“ gegeben. <em>Queues</em> bieten die Methoden <code>add/offer</code>, <code>remove/poll</code> sowie <code>element/peek</code> an, um auf die Elemente in Form einer Warteschlange zuzugreifen. Beim Typ <em>Map</em> handelt es sich eigentlich um keine <em>echte </em>Collection. Das Collection-Interface wird zwar tatsächlich nicht implementiert, dennoch werden auch Maps zum Speichern vieler Elemente, also als Collection, genutzt. Der größte Unterschied zu den restlichen Collections ist, dass aufgrund dieser Tatsache kein Iterator zum Durchlaufen der Elemente erzeugt werden kann. Der Zugriff wird stattdessen über die Methoden <code>keySet</code>, <code>values</code> und <code>entrySet</code> (die drei sog. „Views“) realisiert.</p>
<p>Des weiteren fällt auf, dass viele der Collections nicht thread-safe sind. Dieses Problem lässt sich relativ einfach mit der Utility-Klasse <em>Collections</em> lösen. Diese bietet zum Beispiel für Maps die statische Methode</p>
<p><code>Map Collections.synchronizedMap(Map map)</code></p>
<p><code></code>an, die eine Map zurückliefert, die die selben Elemente enthält, deren Methoden aber <code>synchronized</code> sind. Bemerkenswert ist dabei auch, dass diese Methode auch für den Typ Map existiert, obwohl es sich bei dieser um keine Collection handelt.</p>
<p>Außerdem hat prinzipiell auch jede Klasse die Möglichkeit mit <code>null</code>-Werten umgehen zu können. Hierfür muss lediglich bei der Erzeugung der Collection ein passender <em>Comparator</em> übergeben werden, der in der Lage ist, auch <code>null</code>-Werte zu sortieren. Dieses Problem besteht nämlich ausschließlich bei den Implementierungen, die die Elemente mittels einem Comparator sortieren müssen.</p>
<p>Zu guter Letzt ist es wichtig zu wissen, dass die verschiedenen Implementierungen unterschiedlich schnell sind. Die Thread-sicheren Varianten sind normalerweise immer langsamer als ihre nicht-synchronisierten Alternativen. Aber auch mögliche Tuningparameter wie beispielsweise initial-capacity oder load-factor sollten sinnvollerweise an den konkreten Fall angepasst werden. Für welche Implementierung man sich letztlich entscheidet muss von der häufigsten Verwendungsart abhängig gemacht werden. Zum Beispiel ist eine <em>ArrayList</em> beim Zugriff auf ein indiziertes Element schneller als eine <em>LinkedList</em>. Die <em>LinkedList</em> ist dafür beim Einfügen neuer Elemente performanter. Da diese Implementierungsdetails allerdings über diesen Überblick hinausgehen, ist dafür im konkreten Anwendungsfall die offizielle API zu konsultieren.</p>
<p>Hier die Übersichtstabelle:</p>
<table width="454" border="0" rules="NONE" cellspacing="0">
<col width="219" />
<col width="208" />
<col width="208" />
<col width="208" />
<col width="208" />
<col width="208" />
<tbody>
<tr>
<td align="LEFT" width="219" height="39"></td>
<td align="CENTER" width="208"><strong><span style="font-size: small">Typ</span></strong></td>
<td align="CENTER" width="208"><strong><span style="font-size: small">Duplikate erlaubt</span></strong></td>
<td align="CENTER" width="208"><strong><span style="font-size: small">Null erlaubt</span></strong></td>
<td align="CENTER" width="208"><strong><span style="font-size: small">Thread-Safe</span></strong></td>
<td align="CENTER" width="208"><strong><span style="font-size: small">Ordered</span></strong></td>
</tr>
<tr>
<td align="LEFT" height="39"><strong><span style="font-size: small">ArrayList</span></strong></td>
<td align="CENTER" bgcolor="#E6E6FF">List</td>
<td align="CENTER" bgcolor="#E6E6FF">Ja</td>
<td align="CENTER" bgcolor="#E6E6FF">Ja</td>
<td align="CENTER" bgcolor="#E6E6FF">Nein</td>
<td align="CENTER" bgcolor="#E6E6FF">Insertion</td>
</tr>
<tr>
<td align="LEFT" height="39"><strong><span style="font-size: small">LinkedList</span></strong></td>
<td align="CENTER" bgcolor="#E6E6FF">List, Stack, Queue</td>
<td align="CENTER" bgcolor="#E6E6FF">Ja</td>
<td align="CENTER" bgcolor="#E6E6FF">Ja</td>
<td align="CENTER" bgcolor="#E6E6FF">Nein</td>
<td align="CENTER" bgcolor="#E6E6FF">abhängig vom Typ</td>
</tr>
<tr>
<td align="LEFT" height="39"><strong><span style="font-size: small">Vector</span></strong></td>
<td align="CENTER" bgcolor="#E6E6FF">List</td>
<td align="CENTER" bgcolor="#E6E6FF">Ja</td>
<td align="CENTER" bgcolor="#E6E6FF">Ja</td>
<td align="CENTER" bgcolor="#E6E6FF">Ja</td>
<td align="CENTER" bgcolor="#E6E6FF">Insertion</td>
</tr>
<tr>
<td align="LEFT" height="39"><strong><span style="font-size: small">Stack</span></strong></td>
<td align="CENTER" bgcolor="#E6E6FF">Stack</td>
<td align="CENTER" bgcolor="#E6E6FF">Ja</td>
<td align="CENTER" bgcolor="#E6E6FF">Ja</td>
<td align="CENTER" bgcolor="#E6E6FF">Ja</td>
<td align="CENTER" bgcolor="#E6E6FF">LIFO</td>
</tr>
<tr>
<td align="LEFT" height="39"><strong><span style="font-size: small">HashSet</span></strong></td>
<td align="CENTER" bgcolor="#E6E6FF">Set</td>
<td align="CENTER" bgcolor="#E6E6FF">Nein</td>
<td align="CENTER" bgcolor="#E6E6FF">Ja</td>
<td align="CENTER" bgcolor="#E6E6FF">Nein</td>
<td align="CENTER" bgcolor="#E6E6FF">Nein</td>
</tr>
<tr>
<td align="LEFT" height="39"><strong><span style="font-size: small">LinkedHashSet</span></strong></td>
<td align="CENTER" bgcolor="#E6E6FF">Set</td>
<td align="CENTER" bgcolor="#E6E6FF">Nein</td>
<td align="CENTER" bgcolor="#E6E6FF">Ja</td>
<td align="CENTER" bgcolor="#E6E6FF">Nein</td>
<td align="CENTER" bgcolor="#E6E6FF">Insertion</td>
</tr>
<tr>
<td align="LEFT" height="39"><strong><span style="font-size: small">TreeSet</span></strong></td>
<td align="CENTER" bgcolor="#E6E6FF">SortedSet</td>
<td align="CENTER" bgcolor="#E6E6FF">Nein</td>
<td align="CENTER" bgcolor="#E6E6FF">Nein</td>
<td align="CENTER" bgcolor="#E6E6FF">Nein</td>
<td align="CENTER" bgcolor="#E6E6FF">Keys</td>
</tr>
<tr>
<td align="LEFT" height="39"><strong><span style="font-size: small">HashMap</span></strong></td>
<td align="CENTER" bgcolor="#E6E6FF">Map</td>
<td align="CENTER" bgcolor="#E6E6FF">Nur Values</td>
<td align="CENTER" bgcolor="#E6E6FF">Ja</td>
<td align="CENTER" bgcolor="#E6E6FF">Nein</td>
<td align="CENTER" bgcolor="#E6E6FF">Nein</td>
</tr>
<tr>
<td align="LEFT" height="39"><strong><span style="font-size: small">LinkedHashMap</span></strong></td>
<td align="CENTER" bgcolor="#E6E6FF">Map</td>
<td align="CENTER" bgcolor="#E6E6FF">Nur Values</td>
<td align="CENTER" bgcolor="#E6E6FF">Ja</td>
<td align="CENTER" bgcolor="#E6E6FF">Nein</td>
<td align="CENTER" bgcolor="#E6E6FF">Insertion</td>
</tr>
<tr>
<td align="LEFT" height="39"><strong><span style="font-size: small">TreeMap</span></strong></td>
<td align="CENTER" bgcolor="#E6E6FF">SortedMap</td>
<td align="CENTER" bgcolor="#E6E6FF">Nur Values</td>
<td align="CENTER" bgcolor="#E6E6FF">Nein</td>
<td align="CENTER" bgcolor="#E6E6FF">Nein</td>
<td align="CENTER" bgcolor="#E6E6FF">Keys</td>
</tr>
<tr>
<td align="LEFT" height="39"><strong><span style="font-size: small">Hashtable</span></strong></td>
<td align="CENTER" bgcolor="#E6E6FF">Map</td>
<td align="CENTER" bgcolor="#E6E6FF">Nur Values</td>
<td align="CENTER" bgcolor="#E6E6FF">Nein</td>
<td align="CENTER" bgcolor="#E6E6FF">Ja</td>
<td align="CENTER" bgcolor="#E6E6FF">Nein</td>
</tr>
<tr>
<td align="LEFT" height="39"><strong><span style="font-size: small">Concurrent</span></strong><strong><span style="font-size: small"><br />
HashMap</span></strong></td>
<td align="CENTER" bgcolor="#E6E6FF">Map</td>
<td align="CENTER" bgcolor="#E6E6FF">Nur Values</td>
<td align="CENTER" bgcolor="#E6E6FF">Ja</td>
<td align="CENTER" bgcolor="#E6E6FF">Ja</td>
<td align="CENTER" bgcolor="#E6E6FF">Nein</td>
</tr>
<tr>
<td align="LEFT" height="39"><strong><span style="font-size: small">PriorityQueue</span></strong></td>
<td align="CENTER" bgcolor="#E6E6FF">Queue</td>
<td align="CENTER" bgcolor="#E6E6FF">Ja</td>
<td align="CENTER" bgcolor="#E6E6FF">Nein</td>
<td align="CENTER" bgcolor="#E6E6FF">Nein</td>
<td align="CENTER" bgcolor="#E6E6FF">Via Comparator</td>
</tr>
<tr>
<td align="LEFT" height="39"><strong><span style="font-size: small">Priority</span></strong><strong><span style="font-size: small"><br />
BlockingQueue</span></strong></td>
<td align="CENTER" bgcolor="#E6E6FF">Queue</td>
<td align="CENTER" bgcolor="#E6E6FF">Ja</td>
<td align="CENTER" bgcolor="#E6E6FF">Nein</td>
<td align="CENTER" bgcolor="#E6E6FF">Ja</td>
<td align="CENTER" bgcolor="#E6E6FF">Via Comparator</td>
</tr>
<tr>
<td align="LEFT" height="39"><strong><span style="font-size: small">Concurrent</span></strong><strong><span style="font-size: small"><br />
LinkedQueue</span></strong></td>
<td align="CENTER" bgcolor="#E6E6FF">Queue</td>
<td align="CENTER" bgcolor="#E6E6FF">Ja</td>
<td align="CENTER" bgcolor="#E6E6FF">Ja</td>
<td align="CENTER" bgcolor="#E6E6FF">Ja</td>
<td align="CENTER" bgcolor="#E6E6FF">FIFO</td>
</tr>
</tbody>
</table>
]]></content:encoded>
			<wfw:commentRss>http://blog.triona.de/development/java/1444.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Generating build numbers in web applications using maven</title>
		<link>http://blog.triona.de/development/java/generating-build-numbers-in-web-applications-using-maven.html</link>
		<comments>http://blog.triona.de/development/java/generating-build-numbers-in-web-applications-using-maven.html#comments</comments>
		<pubDate>Sun, 19 Feb 2012 14:00:24 +0000</pubDate>
		<dc:creator>Marc Brosius</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JEE]]></category>
		<category><![CDATA[Build]]></category>
		<category><![CDATA[build number]]></category>
		<category><![CDATA[HTML]]></category>
		<category><![CDATA[JSF]]></category>
		<category><![CDATA[JSP]]></category>
		<category><![CDATA[Maven]]></category>
		<category><![CDATA[Maven Plugins]]></category>
		<category><![CDATA[Subversion]]></category>
		<category><![CDATA[web application]]></category>

		<guid isPermaLink="false">http://blog.triona.de/?p=1398</guid>
		<description><![CDATA[Problem: You want to create a build number in the web front end of your application (e.g. to have it on screenshots appended to bug reports during user acceptance test). You are using maven for your builds and your code is under source control (e.g. using subversion). Solution: All you need is some maven plugins [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Problem:</strong><br />
You want to create a build number in the web front end of your application (e.g. to have it on screenshots appended to bug reports during user acceptance test).<br />
You are using maven for your builds and your code is under source control (e.g. using subversion).</p>
<p><strong>Solution:</strong><br />
All you need is some maven plugins and a place to write the build number to.<br />
In this case I&#8217;d like to have the maven version number followed by the subversion revision number and a timestamp of the build date like this:</p>
<blockquote><p>Version: 1.0-SNAPSHOT r1 Built on: 2012-02-19 13:41</p></blockquote>
<p>First I create a version.html in src/main/resources or src/main/templates or something like that:</p>

<div class="wp_syntax"><div class="code"><pre class="html" style="font-family:monospace;">&lt;div class=&quot;version&quot;&gt;Version: @VERSION@&lt;/div&gt;
&lt;div class=&quot;builton&quot;&gt;Built on: @BUILTON@&lt;/div&gt;</pre></div></div>

<p>As you can see there are two placeholders (@VERSION@ and @BUILTON@)<br />
Next I insert and configure the plugins to create the version info and the timestamp and to replace the placeholders with them in my pom.xml:</p>
<blockquote><p>
&lt;plugin&gt;<br />
	&lt;groupId&gt;org.codehaus.mojo&lt;/groupId&gt;<br />
	&lt;artifactId&gt;maven-buildnumber-plugin&lt;/artifactId&gt;<br />
	&lt;executions&gt;<br />
		&lt;execution&gt;<br />
			&lt;phase&gt;validate&lt;/phase&gt;<br />
		    &lt;goals&gt;<br />
		    	&lt;goal&gt;create&lt;/goal&gt;<br />
		    &lt;/goals&gt;<br />
		&lt;/execution&gt;<br />
	&lt;/executions&gt;<br />
	&lt;configuration&gt;<br />
		&lt;doCheck&gt;true&lt;/doCheck&gt;<br />
		&lt;doUpdate&gt;false&lt;/doUpdate&gt;<br />
	&lt;/configuration&gt;<br />
&lt;/plugin&gt;
</p></blockquote>
<p>This creates a property named buildNumber with the revision number of the checked out code. The configuration doCheck=true causes a check whether there are any uncommitted changes. If there were any, the build would fail. With doUpdate you could instruct the build to execute a svn update prior to execution of the build.<br />
For more info about this plugin see here:<br />
<a href="http://mojo.codehaus.org/buildnumber-maven-plugin/" title="http://mojo.codehaus.org/buildnumber-maven-plugin/" target="_blank">http://mojo.codehaus.org/buildnumber-maven-plugin/</a><br />
We could also use this plugins goal &#8220;create-timestamp&#8221; to create the timestamp, but since maven itself provides a property for that we just need to set that properties format in the properties section of our pom:</p>
<blockquote><p>
&lt;properties&gt;<br />
    &lt;maven.build.timestamp.format&gt;yyyy-MM-dd HH:mm&lt;/maven.build.timestamp.format&gt;<br />
&lt;/properties&gt;
</p></blockquote>
<p>Now having all we need, we need to replace the placeholders in our html and copy the replacement to our target folder.</p>
<blockquote><p>
			&lt;plugin&gt;<br />
	           &lt;groupId&gt;com.google.code.maven-replacer-plugin&lt;/groupId&gt;<br />
	           &lt;artifactId&gt;maven-replacer-plugin&lt;/artifactId&gt;<br />
	           &lt;version&gt;1.4.0&lt;/version&gt;<br />
	           &lt;executions&gt;<br />
	               &lt;execution&gt;<br />
	                   &lt;phase&gt;prepare-package&lt;/phase&gt;<br />
	                   &lt;goals&gt;<br />
	                       &lt;goal&gt;replace&lt;/goal&gt;<br />
	                   &lt;/goals&gt;<br />
	               &lt;/execution&gt;<br />
	           &lt;/executions&gt;<br />
	           &lt;configuration&gt;<br />
	           	  &lt;file&gt;src/main/templates/version.html&lt;/file&gt;<br />
	              &lt;outputFile&gt;target/version.html&lt;/outputFile&gt;<br />
	               &lt;regex&gt;false&lt;/regex&gt;<br />
	               &lt;replacements&gt;<br />
	                   &lt;replacement&gt;<br />
	                       &lt;token&gt;@VERSION@&lt;/token&gt;<br />
	                       &lt;value&gt;${version} r${buildNumber}&lt;/value&gt;<br />
	                   &lt;/replacement&gt;<br />
	                   &lt;replacement&gt;<br />
	                       &lt;token&gt;@BUILTON@&lt;/token&gt;<br />
	                       &lt;value&gt;${maven.build.timestamp}&lt;/value&gt;<br />
	                   &lt;/replacement&gt;<br />
	               &lt;/replacements&gt;<br />
	           &lt;/configuration&gt;<br />
	       &lt;/plugin&gt;
</p></blockquote>
<p>This replaces the placeholders in src/main/templates/version.html with the values and writes the result into the specified target folder.<br />
More info about this plugin is provided here:<br />
<a href="http://code.google.com/p/maven-replacer-plugin/" title="http://code.google.com/p/maven-replacer-plugin/" target="_blank">http://code.google.com/p/maven-replacer-plugin/</a><br />
Having that, you just need to include that into your pages. That&#8217;s it.</p>
<p>Conclusion:<br />
We now have a build number on our pages.<br />
There for sure is room to improve this solution and it is for sure not the only solution. But it did the job for me and I hope it will help you.<br />
If I should have forgotten something in this description, do not hesitate to give me feedback via the comments form.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.triona.de/development/java/generating-build-numbers-in-web-applications-using-maven.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Websphere 7 und JSF 2.0 mit Richfaces 4.x</title>
		<link>http://blog.triona.de/development/java/websphere-7-und-jsf-2-0-mit-richfaces-4-x.html</link>
		<comments>http://blog.triona.de/development/java/websphere-7-und-jsf-2-0-mit-richfaces-4-x.html#comments</comments>
		<pubDate>Mon, 13 Feb 2012 20:14:10 +0000</pubDate>
		<dc:creator>Bernhard Molz</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[JEE]]></category>
		<category><![CDATA[Triona]]></category>
		<category><![CDATA[JavaEE]]></category>
		<category><![CDATA[JSF 1.2]]></category>
		<category><![CDATA[JSF 2.0]]></category>
		<category><![CDATA[Richfaces]]></category>
		<category><![CDATA[Websphere]]></category>

		<guid isPermaLink="false">http://blog.triona.de/?p=1355</guid>
		<description><![CDATA[Problem Websphere 7 als Java-EE5-Applikationsserver bietet keine JSF-2.0-Implementierung an &#8211; zu Zeiten von Java-EE5 war noch JSF 1.2 aktuell. Wie es denoch geht, will ich hier zeigen. Websphere 7 als Java-EE5-Applikationsserver bringt zwei JSF-1.2-Implementierungen mit &#8211; eine (leicht modifizierte) Sun-Referenz-Implementierung und MyFaces. Wer bereits mit JSF 2.0 gearbeitet hat, wird den Weg zurück nach JSF [...]]]></description>
			<content:encoded><![CDATA[<h3>Problem</h3>
<p>Websphere 7 als Java-EE5-Applikationsserver bietet keine JSF-2.0-Implementierung<br />
an &#8211; zu Zeiten von Java-EE5 war noch JSF 1.2 aktuell. Wie es denoch geht, will<br />
ich hier zeigen.</p>
<p>Websphere 7 als Java-EE5-Applikationsserver bringt zwei JSF-1.2-Implementierungen<br />
mit &#8211; eine (leicht modifizierte) Sun-Referenz-Implementierung und MyFaces. Wer<br />
bereits mit JSF 2.0 gearbeitet hat, wird den Weg zurück nach JSF 1.2 sicher nicht<br />
gehen wollen, deshalb habe ich hier die Schritte aufgeschrieben, die notwendig sind,<br />
um Websphere 7 (und auch WS8!) JSF 2.0 mit Richfaces schmackhaft<br />
zu machen.</p>
<h3>Lösung</h3>
<p>1. Die zu deployende WAR/EAR-Datei muss Mojarra 2.0.4 oder 2.0.8 (nicht 2.1.x,<br />
nicht 2.0.2) enthalten.<br />
In der Regel ist das eine jsf-api.jar und eine jsf-impl.jar (manchmal<br />
auch eine einzelne Datei namens javax.faces-2.x.x.jar).<br />
Diese JSF-Implementierung (Mojarra 2.0.4) kommt in das Verzeichnis WEB-INF/lib.</p>
<p>Wer Maven nutzt, kann folgende Dependency hinzufügen:</p>
<pre>&lt;dependency&gt;
  &lt;groupId&gt;org.glassfish&lt;/groupId&gt;
  &lt;artifactId&gt;javax.faces&lt;/artifactId&gt;
  &lt;version&gt;2.0.4&lt;/version&gt;
&lt;/dependency&gt;</pre>
<p>Neuere Versionen von JSF (2.1.+) benötigen die Servlet-API 3.0, die<br />
normaler Weise nur bei JavaEE6-Servern zu finden ist.<br />
Versucht man, andere Versionen als die JSF 2.0.4/2.0.8 zu nutzen, dann steigt<br />
die Web-Anwendung mglw. mit folgender Fehlermeldung im Log aus:</p>
<pre>javax.servlet.ServletException: SRVE0207E: Es wurde eine nicht abgefangene Initialisierungsausnahme vom Servlet erstellt.
at com.ibm.ws.webcontainer.servlet.ServletWrapper.init(ServletWrapper.java:434)
at com.ibm._jsp._index._jspService(_index.java:85)
Caused by: java.lang.IllegalStateException: Die Anwendung wurde bei Systemstart nicht einwandfrei initialisiert,
Factory konnte nicht gefunden werden: javax.faces.context.FacesContextFactory. Rügriff versucht.
at javax.faces.FactoryFinder.getFactory(FactoryFinder.java:270)</pre>
<p>2. Die <strong>web.xml</strong> muss folgenden Eintrag enthalten, um JSF zu initialisieren:</p>
<pre>&lt;listener&gt;
  &lt;listener-class&gt;com.sun.faces.config.ConfigureListener&lt;/listener-class&gt;
&lt;/listener&gt;</pre>
<p>Im Websphere-Log (%websphere%/profiles/AppSrv01/logs/server1/SystemOut.log) wird der Start<br />
von JSF 2.0.4 mitgeloggt:</p>
<pre>[29.01.12 01:36:08:000 CET] 0000001b config I
Mojarra 2.0.4 (FCS b09) für Kontext '/CompositeComp' wird initialisiert.</pre>
<p>3. Der Websphere-Log beklagt sich über eine fehlende Zuweisung des Mime-Typs für xhtml,<br />
für den Fall, dass Dateien mit der Endung .xhtml als JSF-Datei erkannt werden.<br />
Dazu muss in der (applikationsbezogenen oder der allgemeinen) <strong>web.xml</strong> folgender<br />
Eintrag hinzugefügt werden:</p>
<pre>&lt;mime-mapping&gt;
  &lt;extension&gt;xhtml&lt;/extension&gt;
  &lt;mime-type&gt;application/xhtml+xml&lt;/mime-type&gt;
&lt;/mime-mapping&gt;</pre>
<p>4. Wir fügen unserem Projekt Richfaces hinzu.<br />
<a href="https://community.jboss.org/wiki/GettingStartedWithRichFaces4x" title="Getting started with RichFaces 4.x">Getting Started</a><br />
Der Websphere-Log gibt jetzt u.a. folgende Warnung aus:</p>
<pre>
[29.01.12 01:36:10:015 CET] 0000001b Config W
org.richfaces.javascript.ClientServiceConfigParser parse Found JavaScript function definition
for class javax.validation.constraints.NotNull, but that class is not presented
</pre>
<p>Möchte man javascriptseitige Bean-Validierung (JSR330) nutzen, dann sind diese JAR-<br />
Dateien noch nach WEB-INF/lib zu kopieren:<br />
* validation-api.jar (version 1.0.0.GA)<br />
* hibernate-validator.jar (version 4.2 or higher)<br />
Siehe <a title="http://docs.jboss.org/richfaces/latest_4_1_X/ Developer_Guide/en-US/html/chap-Developer_Guide-Getting_started_with_RichFaces.html" href="http://docs.jboss.org/richfaces/latest_4_1_X/ Developer_Guide/en-US/html/chap-Developer_Guide-Getting_started_with_RichFaces.html">http://docs.jboss.org/richfaces/latest_4_1_X/<br />
Developer_Guide/en-US/html/chap-Developer_Guide-Getting_started_with_RichFaces.html<br />
</a><br />
Natürlich kann man sich diesen Schritt sparen, wenn nur serverseitig (und nicht per JS)<br />
validiert wird.</p>
<p>Validation-API:</p>
<pre>&lt;groupId&gt;javax.validation&lt;/groupId&gt;
&lt;artifactId&gt;validation-api&lt;/artifactId&gt;
&lt;version&gt;1.0.0.GA&lt;/version&gt;</pre>
<p>Hibernate-Validator:</p>
<pre>&lt;artifactId&gt;hibernate-validator-parent&lt;/artifactId&gt;
&lt;groupId&gt;org.hibernate&lt;/groupId&gt;
&lt;version&gt;4.2.0.Final&lt;/version&gt;</pre>
<p>5. Es wird allgemein empfohlen, eine &#8220;Gemeinsam genutzte isolierte Bibliothek&#8221; anzulegen,<br />
falls nicht die mit dem Websphere mitgelieferten JSF-Implementierungen (JSF1.2 und<br />
MyFaces) genutzt werden, sondern externe.<br />
In meinem Fall hat das nicht geklappt. Es ging nur dann, wenn ich meiner WAR-Datei die<br />
JSF-Dateien hinzugefügt und den Listener in der web.xml eingestellt hatte.<br />
So geht&#8217;s laut IBM:<br />
<a title="JavaServer-Faces-Implementierung konfigurieren" href="http://publib.boulder.ibm.com/infocenter/wasinfo/v7r0/index.jsp?topic=/com.ibm.websphere.nd.multiplatform.doc/info/ae/ae/tweb_jsf.html"><br />
JavaServer-Faces-Implementierung konfigurieren</a></p>
<p>6. Es wird immer noch der EL-Parser von IBM genommen, so dass die Auswertung von<br />
Methoden-Parametern nicht möglich ist. Ein #{myBean.write(&#8216;Hallo&#8217;)} führt folglich<br />
zu einem Fehler.</p>
<pre>org.apache.el.parser.ParseException: Encountered "(" at line 1, column 22.
Was expecting one of: "}" ... "." ... "[" ... "&gt;"
at org.apache.el.parser.ELParser.generateParseException(ELParser.java:2142)</pre>
<p>Wir müssen jetzt also auch den EL-Parser aktualisieren. Wie das geht,<br />
wird dort beschrieben:</p>
<p><a title="http://rueprich.de/bloggt/2010/06/expression-language-2-2-mit-maven-und-tomcat" href="http://rueprich.de/bloggt/2010/06/expression-language-2-2-mit-maven-und-tomcat">http://rueprich.de/bloggt/2010/06/expression-language-2-2-mit-maven-und-tomcat<br />
</a></p>
<pre>&lt;dependency&gt;
  &lt;groupId&gt;javax.el&lt;/groupId&gt;
  &lt;artifactId&gt;el-api&lt;/artifactId&gt;
  &lt;version&gt;2.2&lt;/version&gt;
&lt;/dependency&gt;

&lt;dependency&gt;
  &lt;groupId&gt;org.glassfish.web&lt;/groupId&gt;
  &lt;artifactId&gt;el-impl&lt;/artifactId&gt;
  &lt;version&gt;2.2&lt;/version&gt;
&lt;/dependency&gt;</pre>
<p>web.xml:</p>
<pre>&lt;context-param&gt;
  &lt;param-name&gt;com.sun.faces.expressionFactory&lt;/param-name&gt;
  &lt;param-value&gt;com.sun.el.ExpressionFactoryImpl&lt;/param-value&gt;
&lt;/context-param&gt;</pre>
<p>Im Websphere-Log erscheint folgende Warnung:</p>
<pre>I JSF1027: [null Die ELResolvers für JSF wurden nicht im JSP-Container registriert.</pre>
<p>Diese Meldung werde ich ignorieren, da ich jetzt dank JSF 2.0 kein JSP mehr verwenden muss.</p>
<p>7. Sich freuen über eine aktuelle JSF-2.0-Implementierung mit ebenso aktueller Expression<br />
Language.</p>
<h3>Was bringt die Akutalisierung auf JSF 2.0 für den Entwickler?</h3>
<p>Ich will die aus meiner Sicht wichtigen Veränderungen an Minibeispielen kurz aufzeigen:<br />
* ManagedBean und ManagedProperty via Annotation statt über XML-Dateien.<br />
In JSF 1.2 sind ManagedBeans aufwändig zu konfigurieren. Neben der Java-Klasse<br />
selbst hat man noch eine Menge XML-Konfiguration vor sich:<br />
<strong>faces-config.xml</strong>:</p>
<pre>&lt;managed-bean&gt;
  &lt;managed-bean-name&gt;carBean&lt;/managed-bean-name&gt;
  &lt;managed-bean-class&gt;de.triona.view.CarBean&lt;/managed-bean-class&gt;
  &lt;managed-bean-scope&gt;session&lt;/managed-bean-scope&gt;
  &lt;managed-property&gt;
    &lt;property-name&gt;bikeBean&lt;/property-name&gt;
  &lt;/managed-property&gt;
&lt;/managedBean&gt;
&lt;managed-bean&gt;
  &lt;managed-bean-name&gt;bikeBean&lt;/managed-bean-name&gt;
  &lt;managed-bean-class&gt;de.triona.view.BikeBean&lt;/managed-bean-class&gt;
  &lt;managed-bean-scope&gt;session&lt;/managed-bean-scope&gt;
&lt;/managedBean&gt;</pre>
<p>In JSF 2.0 reduziert sich das auf eine Java-Klasse mit Annotationen:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">@ManagedBean
@SessionScoped
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> CarBean <span style="color: #009900;">&#123;</span>
  @ManagedProperty<span style="color: #009900;">&#40;</span>value<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;bikeBean&quot;</span><span style="color: #009900;">&#41;</span>
  BikeBean bikeBean<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>* Direkte Navigation an Stelle der indirekten Navigation in <strong>faces-config.xml</strong><br />
* Die AJAX-Komponente f:ajax<br />
Bsp.:</p>
<pre>&lt;h:inputText value="#{bean.text}"&gt;
  &lt;f:ajax event="keyup" execute="@this" render="out"/&gt;
&lt;/h:inputText&gt;
&lt;!-- Dieses Textfeld wird jetzt bei jedem KeyUp-Event neu gerendert--&gt;
&lt;h:outputText id="out" value="#{bean.text}"/&gt;</pre>
<h3>Fazit</h3>
<p>JSF 2.0 auf dem Websphere 7 ist mit einiger Mühe machbar.<br />
<strong>Aber:</strong>Bei meinen Tests auf verschiedenen Rechnern gab es manchmal<br />
Probleme und das Ende der Fahnenstange war doch das mitgelieferte JSF 1.2 -<br />
je nach Patchversion des WS und der mitgelieferten Libraries der Anwendung.</p>
<p>Daher ist die Devise: ausprobieren!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.triona.de/development/java/websphere-7-und-jsf-2-0-mit-richfaces-4-x.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Zeitgesteuerte Jobs in Java / JEE (Spring Batch und Quartz-Scheduler)</title>
		<link>http://blog.triona.de/development/zeitgesteuerte-jobs-in-java-jee-spring-batch-und-quartz-scheduler.html</link>
		<comments>http://blog.triona.de/development/zeitgesteuerte-jobs-in-java-jee-spring-batch-und-quartz-scheduler.html#comments</comments>
		<pubDate>Thu, 09 Feb 2012 09:11:27 +0000</pubDate>
		<dc:creator>Joachim Schmidt</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[JEE]]></category>
		<category><![CDATA[ApplicationContext]]></category>
		<category><![CDATA[Batch]]></category>
		<category><![CDATA[Cron]]></category>
		<category><![CDATA[Job]]></category>
		<category><![CDATA[Quartz]]></category>
		<category><![CDATA[Scheduler]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[Spring Batch]]></category>
		<category><![CDATA[Spring Core]]></category>
		<category><![CDATA[Spring Framework]]></category>
		<category><![CDATA[TaskScheduler]]></category>
		<category><![CDATA[Timer]]></category>
		<category><![CDATA[Trigger]]></category>

		<guid isPermaLink="false">http://blog.triona.de/?p=1331</guid>
		<description><![CDATA[Die klassische Batch- bzw. Stapelverarbeitung von Daten bzw. Aufgaben war lange Zeit ein typisches Anwendungsszenario von Mainframe-Systemen. Schaut man sich aber auch mal kleinere Serversysteme und Serversoftware an, stellt man fest, dass auch hier oftmals ähnliche Anwendungsfälle auftreten, die aber meist proprietär umgesetzt werden. Ein Beispiel könnte das zeitgesteuerte, periodische Einlesen einer CSV-Datei in eine [...]]]></description>
			<content:encoded><![CDATA[<p>Die klassische Batch- bzw. Stapelverarbeitung von Daten bzw. Aufgaben war lange Zeit ein typisches Anwendungsszenario von Mainframe-Systemen. Schaut man sich aber auch mal kleinere Serversysteme und Serversoftware an, stellt man fest, dass auch hier oftmals ähnliche Anwendungsfälle auftreten, die aber meist proprietär umgesetzt werden. Ein Beispiel könnte das zeitgesteuerte, periodische Einlesen einer CSV-Datei in eine Datenbank sein. Oder das tägliche Generieren von Rechnungen anhand des aktuellen Datenstandes.</p>
<p>Hat man in seinem System gleich mehrere solcher Anwendungsfälle ausfindig machen können, lohnt sich ein Blick auf Spring Batch [1]. Spring Batch ist ein sehr flexibles Framework für eben genau diese Batchverarbeitung von Daten. Es bietet eine simple Domainlanguage zur deklarativen Formulierung von Jobs und deren Steps, liefert fertige Zugriffsklassen für Datenbank- und Dateianbindung und Verwaltungs- und Monitoringfunktionen für die Jobs und deren ausführbare Instanzen. Das Einlesen einer kommagetrennten CSV-Datei, das Mapping der Spalten zu Attributen einer Fachklasse und das Schreiben der Fachklasse in wieder andere Spalten einer Datenbank ist somit ohne viel selbstgeschriebenen Code in kurzer Zeit erledigt. Weitere Details zu Spring Batch sind im genannten Link [1] zu finden, bzw. in den sehr zu empfehlenden Büchern [2] und [3].</p>
<p>Das einzige was Spring Batch von Haus aus nicht liefert, ist ein Scheduler zum zeitgesteuerten Ausführen der Batch-Jobs. Hier beruft man sich darauf, dass es am Markt etliche gute Scheduler gibt, die man in Spring Batch integrieren kann. Explizit genannt und zur Integration empfohlen sind der TaskScheduler aus dem Spring Framwork [4], oder der bekannte Quartz-Scheduler [5]. Aber auch andere Produkte (wie z.B. die EJB-Timer) lassen sich als Scheduler nutzen.</p>
<p>Spring Batch bietet auch hier fertige Klassen, die z.B. Quartz-Jobs nahtlos mit Batch-Jobs verknüpfen. Auch hier kommt man sehr schnell zu ersten lauffähigen Ergebnissen, wenn man statische Ausführungszeitpunkte zur Entwicklungszeit deklariert. Möchte man mehr Flexibilität, d.h. zur Laufzeit dynamisch Trigger zu Jobs verwalten, dann lohnt es sich, Quartz wieder etwas aus Spring Batch heraus zu lösen, um die komplette Kontrolle darüber zu bekommen.</p>
<p>Eine mögliche Vorgehensweise ist, lediglich die Batch-Jobs im Spring ApplicationContext zu deklarieren und die Quartz-Trigger selbst zu verwalten. Einziges Bindeglied zwischen Quartz und Spring-Batch ist dann ein generischer Quartz-Job, der beliebige Batch-Jobs startet. Im Folgenden wird das näher betrachtet.</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;job</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;csvImportJob&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    ...
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/job<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>Zuerst wird die gewünschte Funktionalität als Batch-Job implementiert. Dies ist nichts besonderes und losgelöst vom Scheduler.</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bean</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;jobScheduler&quot;</span></span>
<span style="color: #009900;">    <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;org.springframework.scheduling.quartz.SchedulerFactoryBean&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;applicationContextSchedulerContextKey&quot;</span></span>
<span style="color: #009900;">             <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;applicationContext&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/bean<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>Das Instantiieren eines Quarz-Schedulers übernimmt Spring Batch, was den Vorteil hat, dass im Context des Schedulers der ApplicationContext von Spring verfügbar ist. Nur dann können wir aus dem Quarz-Job heraus auf den Batch-Job zugreifen.</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000000; font-weight: bold;">class</span> JobStarter <span style="color: #000000; font-weight: bold;">implements</span> org.<span style="color: #006633;">quartz</span>.<span style="color: #006633;">Job</span> <span style="color: #009900;">&#123;</span>
    @Override
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> execute<span style="color: #009900;">&#40;</span>JobExecutionContext context<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> JobExecutionException <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span>
            Scheduler jobScheduler <span style="color: #339933;">=</span> context.<span style="color: #006633;">getScheduler</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            ApplicationContext appContext <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>ApplicationContext<span style="color: #009900;">&#41;</span> jobScheduler.<span style="color: #006633;">getContext</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;applicationContext&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            JobLauncher jobLauncher <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>JobLauncher<span style="color: #009900;">&#41;</span> appContext.<span style="color: #006633;">getBean</span><span style="color: #009900;">&#40;</span>JobLauncher.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            JobRegistry jobRegistry <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>JobRegistry<span style="color: #009900;">&#41;</span> appContext.<span style="color: #006633;">getBean</span><span style="color: #009900;">&#40;</span>JobRegistry.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
            JobDataMap jobDataMap <span style="color: #339933;">=</span> context.<span style="color: #006633;">getJobDetail</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">getJobDataMap</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            Job job <span style="color: #339933;">=</span> jobRegistry.<span style="color: #006633;">getJob</span><span style="color: #009900;">&#40;</span>jobDataMap.<span style="color: #006633;">getString</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;jobName&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
            jobLauncher.<span style="color: #006633;">run</span><span style="color: #009900;">&#40;</span>job, getJobParameters<span style="color: #009900;">&#40;</span>jobDataMap<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">Exception</span> exception<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #666666; font-style: italic;">// ...</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> JobParameters getJobParameters<span style="color: #009900;">&#40;</span>JobDataMap jobDataMap<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// Map Quartz-Job-Data to Batch-Job-Parameters</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Der generische Batch-JobStarter Quartz-Job. Dieser wird durch die definierten Trigger gestartet und die execute-Methode aufgerufen. Hier wird der Spring ApplicationContext geholt und daraus die nötigen Beans zur Batch-Job-Verwaltung. Den Namen des zu startenden Batch-Jobs, genauso wie dessen Batch-JobParameter, werden aus der Quartz-JobDataMap geladen und gemapped.</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">JobDetail jobDetail <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> JobDetail<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;hourlyCsvImport&quot;</span>, <span style="color: #0000ff;">&quot;defaultGroup&quot;</span>, JobStarter.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
jobDetail.<span style="color: #006633;">getJobDataMap</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;jobName&quot;</span>, <span style="color: #0000ff;">&quot;csvImportJob&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// Put additional Batch-JobParameter here</span>
&nbsp;
CronTrigger jobTrigger <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> CronTrigger<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;hourlyTrigger&quot;</span>, <span style="color: #0000ff;">&quot;defaultGroup&quot;</span>, <span style="color: #0000ff;">&quot;0 0 0/1 * * ? *&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
jobScheduler.<span style="color: #006633;">scheduleJob</span><span style="color: #009900;">&#40;</span>jobDetail, jobTrigger<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Zu guter letzt legen wir einen konkreten Quartz-Job an, der unseren Batch-JobStarter aufruft und den übergebenen Batch-Job startet. Für diesen Quartz-Job sind dann beliebige Trigger definierbar und das alles zur Laufzeit verwaltbar.</p>
<p>[1] <a href="http://static.springsource.org/spring-batch/" title="Spring Batch Webseite">Spring Batch Webseite</a><br />
[2] <a href="http://www.amazon.de/Spring-Batch-Action-Arnaud-Cogoluegnes/dp/1935182951" title="Spring Batch in Action">Buch: &#8220;Spring Batch in Action&#8221;</a><br />
[3] <a href="http://www.amazon.de/Pro-Spring-Batch-Michael-Minella/dp/1430234520/" title="Pro Spring Batch">Buch: &#8220;Pro Spring Batch&#8221;</a><br />
[4] <a href="http://static.springsource.org/spring-framework/docs/3.0.5.RELEASE/reference/scheduling.html" title="Spring Framework TaskScheduler">Spring Framework TaskScheduler</a><br />
[5] <a href="http://www.quartz-scheduler.org" title="Quartz Scheduler">Quartz Scheduler Webseite</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.triona.de/development/zeitgesteuerte-jobs-in-java-jee-spring-batch-und-quartz-scheduler.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Expression Language and type conversion</title>
		<link>http://blog.triona.de/development/java/expression-language-and-type-conversion.html</link>
		<comments>http://blog.triona.de/development/java/expression-language-and-type-conversion.html#comments</comments>
		<pubDate>Sun, 05 Feb 2012 16:40:20 +0000</pubDate>
		<dc:creator>Marc Brosius</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JEE]]></category>
		<category><![CDATA[COERCE_TO_ZERO]]></category>
		<category><![CDATA[EL]]></category>
		<category><![CDATA[Expression Language]]></category>
		<category><![CDATA[JBoss]]></category>
		<category><![CDATA[JSF]]></category>
		<category><![CDATA[Specification]]></category>
		<category><![CDATA[Tomcat]]></category>
		<category><![CDATA[type conversion]]></category>

		<guid isPermaLink="false">http://blog.triona.de/?p=1244</guid>
		<description><![CDATA[In my current project we develop a web application using JSF (1.2) / Facelets with RichFaces in the front end and EJB3/Hibernate in the back end. Deployment target is a JBoss 5 application server. We defined some hibernate entities and some backing beens for our Facelets. Nothing special so far. We defined the numeric fields [...]]]></description>
			<content:encoded><![CDATA[<p>In my current project we develop a web application using JSF (1.2) / Facelets with RichFaces in the front end and EJB3/Hibernate in the back end. Deployment target is a JBoss 5 application server.<br />
We defined some hibernate entities and some backing beens for our Facelets. Nothing special so far.</p>
<p>We defined the numeric fields of our entities using the wrapper objects with the goal to store NULL (instead of zero) in the database if nothing was entered in the form.</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">@<span style="color: #003399;">Entity</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> MyEntity<span style="color: #009900;">&#123;</span>
...
   @Column<span style="color: #009900;">&#40;</span>name<span style="color: #339933;">=</span><span style="color: #0000ff;">&quot;NUMERICFIELD&quot;</span><span style="color: #009900;">&#41;</span>
   <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">Integer</span> numericField<span style="color: #339933;">;</span>
...
    <span style="color: #666666; font-style: italic;">//getters and setters</span>
...
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>We access the entities through the backing beans and access their fields directly using their getters and setters using EL (Expression Language) in the Facelets.</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> MyEntity getMyEntity<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">return</span> myEntity<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> setMyEntity<span style="color: #009900;">&#40;</span>MyEntity myEntity<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">myEntity</span> <span style="color: #339933;">=</span> myEntity<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<blockquote><p>
&lt;h:inputText id=&#8221;myInputText0&#8243; value=&#8221;${myBackingBean.myEntity.numericField}&#8221;/&gt;
</p></blockquote>
<p>Due to lack of deeper knowledge of the JSF specifications we were quite surprised seeing zeros instead of nulls in the database after submitting an empty inputText.</p>
<p>After googling around a bit I found some blog and forum posts stating that setting the system property</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">org.<span style="color: #006633;">apache</span>.<span style="color: #006633;">el</span>.<span style="color: #006633;">parser</span>.<span style="color: #006633;">COERCE_TO_ZERO</span><span style="color: #339933;">=</span><span style="color: #000066; font-weight: bold;">false</span></pre></div></div>

<p> &#8211; which is a system property of the embedded Tomcat web container &#8211; would solve our problem. And it actually did. After setting the system property in the jboss&#8217; startup script null values were stored instead of zeros.</p>
<p>But why? What was the story?<br />
So I started searching in the <a href="http://tomcat.apache.org/tomcat-6.0-doc/config/systemprops.html" title="tomcats documentation" target="_blank">tomcats documentation</a> where I found:</p>
<blockquote><table>
<tr>
<td>org.apache.el.parser. COERCE_TO_ZERO</td>
<td>
If true, when coercing EL expressions to numbers &#8220;&#8221; and null will be coerced to zero as required by the specification.</p>
<p>If not specified, the default value of true will be used.</td>
</tr>
</table>
</blockquote>
<p>Oh, </p>
<blockquote><p>&#8230; as required by the specification.</p></blockquote>
<p>Ok, so I took a look into <a href="http://jsp.java.net/spec/jsp-2_1-fr-spec-el.pdf" title="the EL's spec">the EL&#8217;s spec</a> and really, the conversion rules for numbers on page 17 in that document say:</p>
<blockquote><h3>1.18.3 Coerce A to Number type N</h3>
<ul>
<li>If A is null or &#8220;&#8221;, return 0.</li>
<li>&#8230;</li>
</ul>
</blockquote>
<p>So, by setting the stated system property we made Tomcat behave differing from the standard EL.<br />
Our team discussed a little bit and then decided to document it and live with it, because we</p>
<ul>
<li>have full control over the production server,</li>
<li>have a dedicated app server instance for our application and</li>
<li>would have had much effort to change our design as we found problem.</li>
</ul>
<p>Conclusion:<br />
If you designed your application the way we did and face the same problems like we did, you could use the system property as described in this article.<br />
But if you might have to share your production unit with other applications, I strongly recommend a change of your design.<br />
In that case you should imho think about explicit type conversion in your controller / backing bean instead of directly using your entity there.<br />
Further suggestions are appreciated.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.triona.de/development/java/expression-language-and-type-conversion.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Excel VBA Entwicklung (Teil 1): Makros</title>
		<link>http://blog.triona.de/development/excel-vba-development-part-1-macros.html</link>
		<comments>http://blog.triona.de/development/excel-vba-development-part-1-macros.html#comments</comments>
		<pubDate>Sat, 04 Feb 2012 12:57:38 +0000</pubDate>
		<dc:creator>Thomas Wehrspann</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Excel]]></category>
		<category><![CDATA[Makro]]></category>
		<category><![CDATA[VBA]]></category>

		<guid isPermaLink="false">http://blog.triona.de/?p=1180</guid>
		<description><![CDATA[Alle kennen Excel, DAS Tabellenkalkulationsprogramm aus dem Hause Microsoft &#8211; aktuell in der Version 2010 erhältlich. Excel bietet eine Umfangreiche Bibliothek mit Funktionen unter anderem aus den Bereichen Mathematik, Finanz- und Ingenieurswesen. Es bietet Pivottabellen für Auswertungen und vielfältige Möglichkeiten der grafischen Aufbereitung mittels Diagrammen. Zudem liefert Excel mit der Skriptsprache Visual Basic for Applications, [...]]]></description>
			<content:encoded><![CDATA[<p>Alle kennen Excel, DAS Tabellenkalkulationsprogramm aus dem Hause Microsoft &#8211; aktuell in der Version 2010 erhältlich.</p>
<p>Excel bietet eine Umfangreiche Bibliothek mit Funktionen unter anderem aus den Bereichen Mathematik, Finanz- und Ingenieurswesen. Es bietet Pivottabellen für Auswertungen und vielfältige Möglichkeiten der grafischen Aufbereitung mittels Diagrammen. Zudem liefert Excel mit der Skriptsprache Visual Basic for Applications, kurz VBA, die Möglichkeit Makros aufzuzeichnen, um komplexe, sich wiederholende Aufgaben zu automatisieren. Steigt man tiefer in die Programmierung mit VBA ein, kann man eigenen Funktionen und Funktionsbibliotheken entwickeln, bis hin zu einer völlig eigenständigen (aberauf Excel basierenden) Anwendung. Die zur Programmierung nötige Entwicklungsumgebung, der Visual Basic Editor (VBE), liefert Excel gleich mit.</p>
<p>Ich will hier einen kurze Einstieg in die Entwicklung mit Excel VBA bieten.</p>
<h3>Makros</h3>
<p>Die für die meisten einfachste und schnellste Art ein VBA Programm zu schreiben dürfe sein es nicht selbst zu schreiben, sondern die Arbeit dem Makrorekorder zu überlassen.</p>
<p>Vor die Aufzeichnung des ersten Makros hat Excel allerdings die Optionen gesetzt. Die Makrofunktionen befinden sich im Ribbon im Register &#8220;Entwicklertools&#8221;. Dieses Register ist standardmäßig ausgeblendet und wird folgendermaßen sichtbar gemacht:</p>
<ol>
<li>Im Ribbon auf Register &#8220;<em>Datei</em>&#8221; gehen.</li>
<li>Den vorletzten Punkt &#8220;<em>Optionen</em>&#8221; aufrufen.</li>
<li>Im jetzt aufgegangenen Dialog auf der linken Seite &#8220;<em>Menüband anpassen</em>&#8221; wählen</li>
<li>und anschließend in der Liste &#8220;<em>Hauptregisterkarten</em>&#8221; einen Haken bei &#8220;<em>Entwicklertools</em>&#8221; setzen:</li>
</ol>
<p><a href="http://blog.triona.de/wp-content/uploads/2012/02/Blog_ExcelOptionsEntwicklertools.jpg"><img class="alignnone" src="http://blog.triona.de/wp-content/uploads/2012/02/Blog_ExcelOptionsEntwicklertools-300x219.jpg" alt="" width="300" height="219" /></a></p>
<p>Nun können wir auf das Register &#8220;Entwicklertools&#8221; gehen und finden dort im Abschnitts &#8220;Code&#8221; die Makrofunktionen:</p>
<p><a href="http://blog.triona.de/wp-content/uploads/2012/02/Blog_ExcelRibbonCodeMakros.jpg"><img class="alignnone size-full wp-image-1274" src="http://blog.triona.de/wp-content/uploads/2012/02/Blog_ExcelRibbonCodeMakros.jpg" alt="" width="192" height="110" /></a></p>
<p>&nbsp;</p>
<ul>
<li>&#8220;Makros&#8221;<br />
Hier erscheint ein Dialog mit dem man seine vorhandenen Makros verwalten und ausführen kann.<a href="http://blog.triona.de/wp-content/uploads/2012/02/Blog_ExcelMakro.jpg"><img class="alignnone size-thumbnail wp-image-1265" src="http://blog.triona.de/wp-content/uploads/2012/02/Blog_ExcelMakro-150x150.jpg" alt="" width="150" height="150" /></a></li>
<li>&#8220;Makro aufzeichnen&#8221; / &#8220;Aufzeichnung beenden&#8221;<br />
Mit dieser Funktion wird die Aufzeichnung eines Makros gestartet. Dabei werden alle ausgeführten Befehle in ihrer Reihenfolge zur späteren Wiedergabe aufgezeichnet. Auf diese Weise lassen sich komplexe und wiederkehrende Aufgaben automatisieren.<br />
<a href="http://blog.triona.de/wp-content/uploads/2012/02/Blog_ExcelMakroAufzeichnen.jpg"><img class="alignnone size-thumbnail wp-image-1266" src="http://blog.triona.de/wp-content/uploads/2012/02/Blog_ExcelMakroAufzeichnen-150x150.jpg" alt="" width="150" height="150" /></a></li>
<li>&#8220;Relative Aufzeichnung&#8221;<br />
Diese Option legt fest, ob beim Aufzeichnen der Makros die Zellpositionen absolut, oder relativ gespeichert werden sollen. Soll etwa die rechts von A1 liegende Zelle als B1 gespeichert werden, oder als &#8220;Rechts-von-der-aktuellen-Zelle&#8221;.</li>
<li>&#8220;Makrosicherheit&#8221;<br />
Diese Funktion ruft das Excel-Sicherheitscenter auf, wo man die Bedingungen zur Ausführung von Makros einstellen kann.</li>
</ul>
<p>Mit diesem Wissen kann jetzt jeder selbst Makros aufzeichnen:</p>
<ol>
<li>&#8220;Makro aufzeichnen&#8221;.</li>
<li>Name des Makros einstellen.</li>
<li>Arbeitsschritte in Excel abarbeiten.</li>
<li>&#8220;Aufzeichnung beenden&#8221;</li>
</ol>
<p>Über den Dialog &#8220;Makros&#8221; lässt sich das soeben aufgezeichnete Makro nun jederzeit starten und die aufgezeichneten Schnitte werden automatisch nacheinander ausgeführt.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.triona.de/development/excel-vba-development-part-1-macros.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Zeitgesteuerte Jobs in Java / JEE  (EJB-Timer und Quartz-Scheduler)</title>
		<link>http://blog.triona.de/development/java/zeitgesteuerte-jobs-in-java-jee-ejb-timer-und-quartz-scheduler.html</link>
		<comments>http://blog.triona.de/development/java/zeitgesteuerte-jobs-in-java-jee-ejb-timer-und-quartz-scheduler.html#comments</comments>
		<pubDate>Fri, 03 Feb 2012 13:06:47 +0000</pubDate>
		<dc:creator>Michael Graf</dc:creator>
				<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://blog.triona.de/?p=1253</guid>
		<description><![CDATA[Problemstellung: Da wir für eines unserer Projekte zeitgesteuerte Prozesse benötigen und ich gerade am Architekturkonzept schreibe, habe ich verschiedene Technologien evaluiert. Dabei bin ich auf zwei verschiedene Frameworks gestoßen: EJB-Timer Quartz-Scheduler Die Anforderung ist: Zuverlässig in einem bestimmten Intervall (z.B. täglich um 23.30 Uhr oder an jedem Jahresende) eine Reihe von Prozessen auszuführen. Die Lösung [...]]]></description>
			<content:encoded><![CDATA[<h1>Problemstellung:</h1>
<p>Da wir für eines unserer Projekte zeitgesteuerte Prozesse benötigen und ich gerade am Architekturkonzept schreibe, habe ich verschiedene Technologien evaluiert. Dabei bin ich auf zwei verschiedene Frameworks gestoßen:</p>
<ul>
<li>EJB-Timer</li>
<li>Quartz-Scheduler</li>
</ul>
<p>Die Anforderung ist:</p>
<p>Zuverlässig in einem bestimmten Intervall (z.B. täglich um 23.30 Uhr oder an jedem Jahresende) eine Reihe von Prozessen auszuführen. Die Lösung muss mit Java 7 auf dem JBoss 7.0.2 deployed werden.</p>
<p>&nbsp;</p>
<h1>EJB-Timer:</h1>
<h2>Vorteil</h2>
<p>Um den EJB-Timer nutzen zu können müssen keine externen JAR-Dateien gesucht werden, da alles im javax.ejb-Packet enthalten ist. Die erforderliche JAR-Datei ist im JBoss integriert und im Eclipse-Projekt muss lediglich die JBoss 7.0 Runtime Bibliothek hinzugefügt werden.</p>
<h2>Nachteil</h2>
<p>Dafür musste ich leider feststellen, dass der „jboss-as-7.0.2.Final“ den &lt;Timer-Service&gt; nicht aktiviert hat. Um dies zu tun muss man die „Standalone-preview.xml“ laden. Dafür muss die standalone.bat (unter Windows) mit folgendem Parameter gestartet werden:</p>
<ul>
<li>standalone.bat -server-config=standalone-preview.xml</li>
</ul>
<p>Es darf dabei nicht vergessen werden, jegliche Änderung, die in der standalone.xml vorgenommen wurde, jetzt auch nochmal in der standalone-preview.xml einzutragen.</p>
<h2>Java-Code</h2>
<p>Um den Timer-Service zu nutzen, erstellt man eine EJB. Für die Problemstellung bietet sich ein @Singleton an, der per @Startup ausgeführt wird. Mit @Resource bekommt man den SessionContext, der wiederum über die Methode getTimerService() den gewünschten Service anspricht.</p>
<p>Um einen Timer zu erstellen, kennt der Service die Methode createTimer(Date startZeitpunkt, Long intervallInMillisekunden, Serializable nameDesTimers), mit der ein Timer initialisiert wird.</p>
<p>Nach jedem Intervall läuft der Timer in ein Timeout, für das die EJB eine Methode mit der Annotation @Timeout benötigt. Sie muss public void sein und als Übergabeparameter ein Timer-Objekt besitzen. Diese Methode wird bei jedem Timeout ausgeführt.</p>
<h2>Problem</h2>
<p>Beim ersten Ausprobieren war ich voller Euphorie als ich sah, dass in meinem eingestellten Intervall eine Nachricht auf der Konsole erschien. Als ich jedoch ein weiteres Mal deployed habe musste ich feststellen, dass der erste Timer immer noch lief, obwohl ich die War-Datei gelöscht, den JBoss beendet und wieder neu hochgefahren habe. Nach weiterer Recherche habe ich vom Timer-Service über die Methode getTimers() jeden aktiven Timer mit cancel() beendet. Trotzdem liefen mittlerweile sehr viele Timer weiter.</p>
<p>Scheinbar speichert der JBoss die seralisierten Timer-Objekte in irgendeinen Cache. Jedenfalls habe ich auch nach längerer Recherche nicht herausgefunden wie und wo die abgespeichert werden, bzw. wie ich sie wieder löschen kann. Falls jemand darüber Bescheid weiß, wäre es nett, wenn er mich kontaktieren würde.</p>
<p>&nbsp;</p>
<h1>Quartz-Scheduler</h1>
<h2>Vorteil</h2>
<p>Für den Quartz-Scheduler werden keine Änderungen in der JBoss-Konfiguration benötigt. Lediglich drei JAR-Dateien müssen dem Projekt beigefügt werden.</p>
<ul>
<li>Quartz-all-2.1.3.jar</li>
<li>Slf4j-api-1.6.1.jar</li>
<li>Slf4j-log4j12-1.6.1.jar</li>
</ul>
<p>Diese findet man auf der offiziellen Seite quartz-scheduler.org.</p>
<h2>Java-Code</h2>
<p>Um den Quartz-Scheduler zu nutzen, benötigt man drei Objekte. Einen Job der ausgeführt werden soll, einen Trigger, der sagt wann und in welchem Intervall der Job ausgeführt werden soll und einen Scheduler, in dem der Job einem Trigger zugewiesen und gestartet wird. Für die Implementierung bietet sich eine @Singleton @Startup EJB an, die beim initialisieren (@PostConstruct) die benötigten Objekte erstellt und den Scheduler startet.</p>
<h3>Job</h3>
<p>Man benötigt eine JavaKlasse, die das Interface org.quartz.Job implementiert und folgende Methode überschreibt:</p>
<ul>
<li>public void execute(JobExecutionContext context) throws JobExecutionException</li>
</ul>
<p>In dieser Methode kann beliebiger Java-Code stehen, der zeitgesteuert ausgeführt werden soll.</p>
<p>Dieser Job muss mit einem JobDetail-Objekt verbunden werden:<br />
<code><br />
JobDetail jobHolidayTaken = JobBuilder.newJob(HolidayTakenJob.class)<br />
.withIdentity("HolidayTakenJob", "group1")<br />
.build();<br />
</code><br />
Der wird benötigt, da dem Scheduler ein Trigger zusammen mit einem JobDetail-Objekt übergeben wird.</p>
<h3>Trigger</h3>
<p>Der Trigger dient dazu, ein Intervall und einen Startzeitpunkt zu definieren, in dem ein Job ausgeführt werden soll. Es gibt verschiedene Arten von Triggern. Ich habe den SimpleTrigger und den CronTrigger versucht, wobei dem SimpleTrigger ein Startzeitpunkt und ein Intervall in Millisekunden übergeben werden. Der CronTrigger ist für unsere Problemstellung interessanter, da er über seine CronExpression-language mit dem Kalender klar kommt. Wenn man z.B. an jedem Monatsende einen bestimmten Prozess ausführen will, kommt man mit einem Millisekunden-intervall ohne zusätzliche Logik nicht aus. Die Syntax der CronExpression-language macht das zu einem Kinderspiel:</p>
<p><a href="http://www.quartz-scheduler.org/documentation/quartz-1.x/tutorials/crontrigger">http://www.quartz-scheduler.org/documentation/quartz-1.x/tutorials/crontrigger</a></p>
<p><strong>Hinweis:</strong> Der Link referenziert auf die alte Version 1.x. Ich habe diese gewählt, da dort die Syntax der CronExpression-language sehr schön dargestellt ist. Für weitere Beispiele gibts auf der Seite den Menüpunkt Quartz 2.1.x (2 Einträge weiter oben).</p>
<p><strong>Beispiel:</strong><br />
<code><br />
Calendar startHolidayTaken = new GregorianCalendar();<br />
startHolidayTaken.set(2012, 1, 2, 16, 45, 0);<br />
</code></p>
<p><code>CronTrigger crontriggerHolidayTaken = TriggerBuilder<br />
.newTrigger()<br />
.startAt(startHolidayTaken.getTime())<br />
.withIdentity("cronHolidayTaken")<br />
.withSchedule(CronScheduleBuilder.cronSchedule("0 30 23 * * * *"))<br />
.build();<br />
</code><br />
Dieser Trigger wird täglich um 23:30 Uhr in ein Timeout laufen und den Job ausführen, den er im Scheduler zugewiesen bekommt.</p>
<h3>Scheduler</h3>
<p>Der Scheduler ist so etwas wie der Container, in dem sich die Trigger und die Jobs befinden. Der Scheduler verbindet einen Job mit einem Trigger und sorgt dafür, dass beim Timeout der Job ausgeführt wird.</p>
<p><strong>Beispiel:</strong><br />
<code><br />
Scheduler scheduler = new StdSchedulerFactory().getScheduler();<br />
scheduler.start();<br />
scheduler.scheduleJob(jobHolidayTaken, crontriggerHolidayTaken);<br />
</code></p>
<h1>Fazit</h1>
<p>Ich habe die Evaluierung mit dem EJB-Timer angefangen, da wir sowieso einen EJB-Container in unserem JBoss haben und ich kein weiteres Framework einbinden wollte.</p>
<p>Da ich mich allerdings einen ganzen Tag mit dem EJB-Timer beschäftigt habe und zu keinem zufriedenstellenden Ergebnis gekommen bin (wie schon erwähnt: Ich würde mich über andere Erfahrungen darüber sehr freuen), habe ich mich für den Quartz-Scheduler entschieden, den ich innerhalb kurzer Einarbeitungszeit so zum Laufen bekommen habe, wie ich es brauchte.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.triona.de/development/java/zeitgesteuerte-jobs-in-java-jee-ejb-timer-und-quartz-scheduler.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>jQuery &#8211; noConflict() und die Fallstricke</title>
		<link>http://blog.triona.de/development/jquery-noconflict-und-die-fallstricke.html</link>
		<comments>http://blog.triona.de/development/jquery-noconflict-und-die-fallstricke.html#comments</comments>
		<pubDate>Thu, 26 Jan 2012 00:35:27 +0000</pubDate>
		<dc:creator>Sebastian Adolph</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[alias]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[noConflict]]></category>

		<guid isPermaLink="false">http://blog.triona.de/?p=1230</guid>
		<description><![CDATA[jQuery hat sich in den vergangenen Jahren zu einer weit verbreiten JavaScript &#8211; Bibliothek entwickelt. Der Slogan dieser Bibliothek &#8220;Write less, do more&#8221; ist keine leere Versprechung. Ich habe nun in verschiedenen Projekten jQuery erfolgreich eingesetzt. In einem Projekt bin ich jedoch auf etwas gestossen, was unbekannt war für mich: Die Verwendung von unterschiedlichen Versionen [...]]]></description>
			<content:encoded><![CDATA[<p>jQuery hat sich in den vergangenen Jahren zu einer weit verbreiten JavaScript &#8211; Bibliothek entwickelt. Der Slogan dieser Bibliothek &#8220;Write less, do more&#8221; ist keine leere Versprechung. Ich habe nun in verschiedenen Projekten jQuery erfolgreich eingesetzt. In einem Projekt bin ich jedoch auf etwas gestossen, was unbekannt war für mich: Die Verwendung von unterschiedlichen Versionen von jQuery auf einer geladenen Seite.</p>
<p>Wie erreicht man das Zusammenspiel? Hierfür bietet jQuery die Funktion &#8220;noConflict()&#8221; an.</p>
<p>Ein paar Hintergrundinformationen: Hat man die jQuery &#8211; Bibliothek importiert auf seine Seite, sind die Funktionen von jQuery mittels &#8220;$&#8221; oder &#8220;jQuery&#8221; verfügbar; z.b. &#8216;jQuery(&#8220;div p&#8221;).hide();&#8217; oder &#8216;$(&#8220;div p&#8221;).hide();&#8217;</p>
<p>Verwenden nun andere Skript das &#8216;$&#8217; &#8211; Zeichen um die Funktionen verfügbar zu machen, so kann führt es dazu dass die Funktionen von anderen Bibliotheken nicht verfügbar sind, da jQuery bereits das &#8216;$&#8217; &#8211; Zeichen verwendet.</p>
<p>Was kann also getan werden?</p>
<p style="padding-left: 30px">1. jQuery.noConflict();<br />
2. jQuery(&#8220;div p&#8221;).hide();<br />
3. $(&#8220;content&#8221;).style.display = &#8216;none&#8217;;</p>
<p>Was wird in diesem Abschnitt getan?</p>
<p>1. Hier sagen wir: Gib dem anderen Skript den Alias &#8216;$&#8217; zurück; so dass &#8216;$&#8217; wieder für die andere Bibliothek zur Verfügung steht.<br />
2. Arbeite hier mit &#8220;jQuery&#8221; um jQuery &#8211; spezifische Funktion aufzurufen.<br />
3. Da wir in Zeile 1 &#8220;.noConflict()&#8221; aufgerufen haben, können wir hier mittels &#8216;$&#8217; die Funktionen einer anderen Bibliothek aufrufen.</p>
<p>Mittels &#8220;.noConflict()&#8221; kann auch die Verwendung von 2 unterschiedlichen jQuery &#8211; Versionen realisiert werden:</p>
<p style="padding-left: 30px">1. &lt;script src=&#8221;/domain/lib/js/jQuery1.3.2.js&#8221; type=&#8221;text/javascript&#8221;&gt;&lt;/script&gt;<br />
2. var jq = jQuery.noConflict();<br />
3. &lt;script src=&#8221;/domain/lib/js/jQuery1.5.1.js&#8221; type=&#8221;text/javascript&#8221;&gt;&lt;/script&gt;<br />
4. var player = jQuery.noConflict();</p>
<p>Was wird hier gemacht?</p>
<p style="padding-left: 30px">1. Importieren von einer jQuery &#8211; Bibliothek der Version 1.3.2.<br />
2. Setzen eines Aliasses &#8220;jq&#8221;, so dass alle Funktionalitäten von Version 1.3.2. unter dem Alias &#8220;jq&#8221; verfügbar sind.<br />
3. Importieren von einer jQuery &#8211; Bibliothek der Version 1.5.1.<br />
4. Setzen eines Aliasses &#8220;player&#8221;, so dass alle Funktionalitäten von Version 1.5.1. unter dem Alias &#8220;player&#8221; verfügbar sind.</p>
<p>So weit so gut. Doch welche Fallstrickt ergeben sich hieraus?</p>
<p>Es muss im Code darauf geachtet werden, das die beiden Aliasses konsequent verwendet werden!</p>
<p>Folgendes Beispiel demonstiert diesen Fallstrick:</p>
<p style="padding-left: 30px">function initEvents(id)<br />
{<br />
var _this = jQuery(this);<br />
var container = _this(id);</p>
<p style="padding-left: 30px">var viewSwitch = function(event, state){<br />
&#8230;<br />
}</p>
<p style="padding-left: 30px">viewContainer.bind(&#8220;viewSwitch&#8221;, viewSwitch);<br />
}</p>
<p style="padding-left: 30px">function init(id)<br />
{<br />
initEvents(id);<br />
}</p>
<p>In HTML &#8211; Seite steht folgendes:</p>
<p style="padding-left: 30px">jq(&#8220;body&#8221;).init(&#8220;list&#8221;));</p>
<p>Auf den ersten Blick sieht dieser Code fehlerfrei aus: Es wird eine Funktion aufgeruf, welche wiederum Events registriert (&#8220;bind&#8221;). Dies kann beim Starten der Zeit geschehen.</p>
<p>Das Problem liegt allerdings in der Zeile (<strong>&#8220;var _this = jQuery(this);&#8221;</strong>). Hier wird die aktive jQuery Bibliothek verwendet (unter dem Alias &#8220;jQuery&#8221; verfügbar).<br />
Dieses Event ist nun also unter &#8220;jQuery&#8221; registriert. Wird nun später eine andere jQuery &#8211; Version verwendet z.B. 1.5.1, so ist das vorher registrierte Event nicht mehr bekannt, da es unter jQuery 1.3.2. registriert wurde, nicht jedoch unter jQuery 1.5.1. Merke: jQuery zeigt auf die zuletzt importierte jQuery Bibliothek.</p>
<p>Um dies zu verdeutlichen:</p>
<p style="padding-left: 30px">1. Import von Version 1.3.2<br />
2. Setzen von Alias &#8220;jq&#8221; mittels &#8220;.noConflict()&#8221;.<br />
3. &#8220;jQuery&#8221; und Alias &#8220;jq&#8221; zeigen auf Version 1.3.2.<br />
4. Import von Version 1.5.2. &lt;- Hier entsteht das Problem.<br />
5. Setzen von Alias &#8220;jPlayer&#8221;<br />
6. &#8220;jQuery&#8221; und Alias &#8220;jPlayer&#8221; zeigen auf Version 1.5.1.</p>
<p>Die Lösung des Problems: In der Funktion &#8220;initEvents&#8221; muss statt &#8220;jQuery&#8221; das Alias &#8220;jq&#8221; verwendet werden.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.triona.de/development/jquery-noconflict-und-die-fallstricke.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Wo kommst das Event her?</title>
		<link>http://blog.triona.de/development/wo-kommst-das-event-her.html</link>
		<comments>http://blog.triona.de/development/wo-kommst-das-event-her.html#comments</comments>
		<pubDate>Wed, 25 Jan 2012 23:08:29 +0000</pubDate>
		<dc:creator>Sebastian Adolph</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Eventhandling]]></category>
		<category><![CDATA[Events]]></category>
		<category><![CDATA[Handling]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://blog.triona.de/?p=1225</guid>
		<description><![CDATA[Jeder kennt die Situation: Man entwickelt in Javascript, registriert u.a. viele Events etc. oder man arbeitet an einem bestehenden Projekt und muss das bestehenhe Javascript anpassen. Wie behält man in beiden Fällen den Überblick über die Events auf einer Seite? Ein Tool das ich im Rahmen einer Arbeit bei einem Kunden kennengelernt habe ist &#8220;visual [...]]]></description>
			<content:encoded><![CDATA[<p>Jeder kennt die Situation: Man entwickelt in Javascript, registriert u.a. viele Events etc. oder man arbeitet an einem bestehenden Projekt und muss das bestehenhe Javascript anpassen. Wie behält man in beiden Fällen den Überblick über die Events auf einer Seite?</p>
<p>Ein Tool das ich im Rahmen einer Arbeit bei einem Kunden kennengelernt habe ist &#8220;visual event&#8221;. Dieses Tool ist ein sogenanntes Bookmarklet.</p>
<p>Wie funktioniert es und was macht es? Man fügt per Drag&#8217;n'Drop von der Seite <a title="Visual Event Homepage" href="http://www.sprymedia.co.uk/article/Visual+Event" target="_blank">http://www.sprymedia.co.uk/article/Visual+Event </a>den Button &#8220;Visual Event&#8221; in die Bookmarkleiste des Browsers.</p>
<p>Danach geht man auf eine beliebige Seite deren Events man untersuchen möchte. Ist die Seite geöffnet, klick man auf das zuvor hinzugefügte Bookmark. Nach kurzer Zeit wird die Seite abgedunkelt und es erscheinen kleine, farbige Kästchen die über die Art des Events (Maus: Klick, Doppelklick, Mouseover; HTML &#8211; Events: select, blur, focus sowie UI Events: Key down, Key up etc.).</p>
<p>Fährt man mit der Maus über die Kästchen, erhält man Informationen wo im Skript diese Event behandelt wird.</p>
<p>Sehr hilfreich, wenn man den Überblick verliert, wer was wann wieso wo macht!</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.triona.de/development/wo-kommst-das-event-her.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

