<?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/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Eclipse Stuff</title>
	<atom:link href="http://splitshade.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://splitshade.wordpress.com</link>
	<description>Eclipse, Maven, Wicket - Tutorials und Artikel im Detail</description>
	<lastBuildDate>Thu, 15 Dec 2011 18:57:22 +0000</lastBuildDate>
	<language>de</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='splitshade.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Eclipse Stuff</title>
		<link>http://splitshade.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://splitshade.wordpress.com/osd.xml" title="Eclipse Stuff" />
	<atom:link rel='hub' href='http://splitshade.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Embedded Glassfish &#8211; und der Fisch schwimmt!°°°</title>
		<link>http://splitshade.wordpress.com/2011/12/06/embedded-glassfish-und-der-fisch-schwimmt/</link>
		<comments>http://splitshade.wordpress.com/2011/12/06/embedded-glassfish-und-der-fisch-schwimmt/#comments</comments>
		<pubDate>Tue, 06 Dec 2011 17:00:02 +0000</pubDate>
		<dc:creator>splitshade</dc:creator>
				<category><![CDATA[glassfish]]></category>

		<guid isPermaLink="false">http://splitshade.wordpress.com/?p=796</guid>
		<description><![CDATA[Der folgende Artikel ist Teil meines Buches, das Gerade im Entstehen ist und den Arbeitstitel &#8211; &#8222;Hands on Software&#8220; trägt. Embedded Glassfish Die Verwendung von Eclipse WTP ist mit Sicherheit Geschmackssache. Mir ist das ganze System zu fehlerhaft und zu intransparent. Zu oft schlagen Deployments fehl, WTP deployt kaputte Artefakte in den Applicationserver oder Redeployments [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=splitshade.wordpress.com&amp;blog=5189437&amp;post=796&amp;subd=splitshade&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Der folgende Artikel ist Teil meines Buches, das Gerade im Entstehen ist und den Arbeitstitel &#8211; &#8222;<strong>Hands on Software</strong>&#8220; trägt.</p>
<h1 id="internal-source-marker_0.6918834625151369">Embedded Glassfish</h1>
<p>Die Verwendung von Eclipse WTP ist mit Sicherheit Geschmackssache. Mir ist das ganze System zu fehlerhaft und zu intransparent. Zu oft schlagen Deployments fehl, WTP deployt kaputte Artefakte in den Applicationserver oder Redeployments sind unvollständig.</p>
<p>Im folgenden wird daher ein anderer Ansatz vorgestellt, den ich bevorzuge. Der Glassfish-Applicationserver bietet die Möglichkeit, auch Embedded, also direkt aus dem Code heraus gestartet zu werden.</p>
<p>Zunächst jedoch bauen wir uns eine sehr einfache Webapplikation. Diese muss nicht mehr beinhalten als ein einfaches Servlet.</p>
<p><pre class="brush: java;">

@WebServlet(
urlPatterns = { &quot;/&quot; })
public class EffectiveServlet extends HttpServlet {

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// TODO Auto-generated method stub
super.doGet(req, resp);
resp.getWriter().write(&quot;Hello!!&quot;);
resp.flushBuffer();
}
}

</pre></p>
<p>Damit dieses Servlet kompiliert werden kann, muss die Java-EE-API im Classpath vorhanden sein. Naiver weise deklariere ich folgende Dependency in meinem Gradle- bzw. Maven-Buildfile.</p>
<p><pre class="brush: plain;">
 providedCompile &quot;javax:javaee-api:6.0@jar&quot;
</pre></p>
<p>oder als Maven-Dependency</p>
<p><pre class="brush: plain;">
&lt;dependency&gt;
    &lt;groupId&gt;javax&lt;/groupId&gt;
    &lt;artifactId&gt;javaee-api&lt;/artifactId&gt;
    &lt;version&gt;6.0&lt;/version&gt;
    &lt;scope&gt;provided&lt;/scope&gt;
&lt;/dependency&gt;&lt;/pre&gt;
</pre></p>
<p>Der embedded Glassfish lässt sich sehr einfach starten.</p>
<p>Hierzu erstellt man eine Klasse GlassfishStart.java im Ordner src/test/java.<br />
Es handelt sich hierbei zwar nicht um einen Test, durch die Platzierung in src/test/java kann jedoch die Klasse innerhalb der IDE verwendet werden, ist aber nicht Teil des generierten War-Files.</p>
<p><pre class="brush: java;">
public class GlassfishStart {

        public static void main(String[] args) throws Exception {
            GlassFishProperties gfProp = new GlassFishProperties();
            gfProp.setPort(&quot;http-listener&quot;, 9090);

            GlassFish glassfish = GlassFishRuntime.bootstrap().newGlassFish(gfProp);
            glassfish.start();
        }
}
</pre></p>
<p>Durch diese 4 Zeilen wird ein kompletter Glassfish-Applicationserver auf Port 9090 aus dem Code heraus gestartet.</p>
<p>Hierfür benötigt man zwingend die Embedded-Glassfish Klassen im Classpath.<br />
Folgende Dependency im gradle-buildfile.</p>
<p><pre class="brush: plain;">
testCompile &quot;org.glassfish.extras:glassfish-embedded-all:3.1.1&quot;

</pre></p>
<p>oder als Maven-Dependency</p>
<p><pre class="brush: plain;">

&lt;dependency&gt;
&lt;groupId&gt;org.glassfish.extras&lt;/groupId&gt;
&lt;artifactId&gt;glassfish-embedded-all&lt;/artifactId&gt;
&lt;version&gt;3.1.1&lt;/version&gt;
&lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;

</pre></p>
<p>Durch den Scope testCompile sind die benötigten Klassen zwar in der IDE verfügbar, nicht jedoch zur Laufzeit im war-File.</p>
<p>Wenn man die Klasse startet ist die Enttäuschung jedoch erstmal groß. Folgende nichtssagende Exception erscheint in den Logs:</p>
<p><pre class="brush: plain;">
Exception in thread &quot;main&quot; java.lang.ClassFormatError:
Absent Code attribute in method that is not native or abstract in class file javax/validation/constraints/Pattern$Flag
</pre></p>
<p>Kennen Sie die Lösung bereits?</p>
<p>Die Lösung ist komplexer zu finden als gedacht. Das Problem ist folgende Abhängigkeit im Klassenpfad, die ich bereits zuvor definiert hatte.</p>
<p><pre class="brush: plain;">
 providedCompile &quot;javax:javaee-api:6.0@jar&quot;
</pre></p>
<p>Die javax:javaee-api ist die von Oracle bereitgestellte API für die Java EE Spezifikiation. Diese API besteht lediglich aus den als Schnittstellen deklarierten Klassen. Alle Klassen, die als Implementierung deklariert sind wurden entfernt. Dies schließt sowohl abstrakte Klassen als auch konkrete Implementierungen mit ein. Mit Hilfe dieser Abhängigkeit kann der Code zwar kompiliert, nicht jedoch zur Laufzeit ausgeführt werden. Wird dies trotzdem versucht, resultiert dies genau in der obigen Fehlermeldung.</p>
<p>Ist der Fehler gefunden ist die Lösung trivial. Statt der Abhängigkeit auf die von Oracle bereitgestellte API verwendet M. die Glassfish-eigene API. Hierfür ersetze ich die problematische Dependency mit der folgenden.</p>
<p><pre class="brush: plain;">
providedCompile 'org.glassfish:javaee-api:3.1'
</pre></p>
<p>oder als Maven Dependency</p>
<p><pre class="brush: plain;">
&lt;dependency&gt;
  &lt;groupId&gt;org.glassfish&lt;/groupId&gt;
  &lt;artifactId&gt;javaee-api&lt;/artifactId&gt;
  &lt;version&gt;3.1&lt;/version&gt;
&lt;/dependency&gt;
</pre></p>
<p>Beim nächsten Start erhalte ich wenigstens eine andere Fehlermeldung als zuvor.</p>
<p><pre class="brush: plain;">
java.lang.IllegalStateException: Provider already mapped glassfish:jsf:faces-servlet
</pre></p>
<p>Dies ist weniger schwierig zu lösen als das letzte Problem. Ein Blick auf den Classpath in Eclipse bringt folgendes zu Tage.<br />
<img src="https://lh4.googleusercontent.com/tuVPeIyuMEvPlgWJ8VAjeL3bXV0-ok_rvpsV-nL19brx_2eOQCs2PPwrXFxktsRs5h0nfrbuSzTk5tDQd9_-P-CzyBF-_szv8NLngqZPA-_OmuPucAg" alt="" width="362px;" height="59px;" /></p>
<p>Zusammen mit der zuvor deklarierten Embedded-Glassfish Dependency sind die Glassfish-Klassen doppelt im Classpath vorhanden und werden auch doppelt registriert. Das ist zuviel für den Glassfish und er quittiert den Dienst. Diese Bibliothek wurde durch WTP automatisch in den Classpath eingefügt, lässt sich aber einfach über den Build Path entfernen.<br />
<img src="https://lh4.googleusercontent.com/iTdkThvYlXxLgRDSpnQYj32RcrT8Y41YP2plaMlmPwwDhFQNghGaLxJ2C5iOnSwOl-xbKHNRbqg_Jg0l6iF8xC73kYpYX5E571AGt_1M0ims1XJ8zt8" alt="" width="360px;" height="436px;" /></p>
<h3>Jetzt endlich lässt sich der Embedded-Glassfish starten.</h3>
<p>Was jetzt noch getan werden muss ist das Deployable korrekt zu konfigurieren, da die Sourcen hierfür über das komplette Projekt verteilt sind.<br />
Hierfür bietet die Glassfish-API das ScatteredArchive. Mit einem ScatteredArchive kann ein “virtuelles” War-File zur Laufzeit aufgebaut werden. Der Code hierfür kann so aussehen:</p>
<p><pre class="brush: plain;">
Deployer deployer = glassfish.getDeployer();
ScatteredArchive archive = new ScatteredArchive(appName, ScatteredArchive.Type.WAR);
//kompilierte Klassen hinzufügen.
            archive.addClassPath(new File(&quot;build&quot;, &quot;classes/main&quot;));
            deployer.deploy(archive.toURI());
</pre></p>
<p>Über archive.addClassPath können beliebige Dateien in den Classpath aufgenommen werden und stehen somit zur Laufzeit zur Verfügung.<br />
Die Applikation ist nach dem Start direkt unter <a href="http://localhost:9090/effective">http://localhost:9090/effective</a> erreichbar. Der Kontext-Root-Pfad kann als Konstruktor des ScatteredArchive angegeben werden und wurde hier mit dem Parameter appName befüllt.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/splitshade.wordpress.com/796/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/splitshade.wordpress.com/796/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/splitshade.wordpress.com/796/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/splitshade.wordpress.com/796/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/splitshade.wordpress.com/796/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/splitshade.wordpress.com/796/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/splitshade.wordpress.com/796/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/splitshade.wordpress.com/796/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/splitshade.wordpress.com/796/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/splitshade.wordpress.com/796/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/splitshade.wordpress.com/796/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/splitshade.wordpress.com/796/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/splitshade.wordpress.com/796/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/splitshade.wordpress.com/796/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=splitshade.wordpress.com&amp;blog=5189437&amp;post=796&amp;subd=splitshade&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://splitshade.wordpress.com/2011/12/06/embedded-glassfish-und-der-fisch-schwimmt/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0f446b406cac4629cd7ddf73607054b5?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">splitshade</media:title>
		</media:content>

		<media:content url="https://lh4.googleusercontent.com/tuVPeIyuMEvPlgWJ8VAjeL3bXV0-ok_rvpsV-nL19brx_2eOQCs2PPwrXFxktsRs5h0nfrbuSzTk5tDQd9_-P-CzyBF-_szv8NLngqZPA-_OmuPucAg" medium="image" />

		<media:content url="https://lh4.googleusercontent.com/iTdkThvYlXxLgRDSpnQYj32RcrT8Y41YP2plaMlmPwwDhFQNghGaLxJ2C5iOnSwOl-xbKHNRbqg_Jg0l6iF8xC73kYpYX5E571AGt_1M0ims1XJ8zt8" medium="image" />
	</item>
		<item>
		<title>Top-10 &#8211; Bücher die mich dieses Jahr inspiriert haben</title>
		<link>http://splitshade.wordpress.com/2011/11/24/top-10-bucher-die-mich-dieses-jahr-inspiriert-haben/</link>
		<comments>http://splitshade.wordpress.com/2011/11/24/top-10-bucher-die-mich-dieses-jahr-inspiriert-haben/#comments</comments>
		<pubDate>Thu, 24 Nov 2011 21:00:07 +0000</pubDate>
		<dc:creator>splitshade</dc:creator>
				<category><![CDATA[cool eclipse]]></category>

		<guid isPermaLink="false">http://splitshade.wordpress.com/?p=779</guid>
		<description><![CDATA[Hi, das Jahr ist zwar noch nicht vorüber, trotzdem möchte ich euch schonmal meine Top-10 Bücher 2011 vorstellen. Pragmatic THinking and Learning Das Buch ist spitze. Das Buch hat es tatsächlich geschafft, mich zu inspirieren. Totale Leseempfehlung. The Naked Presenter: Delivering Powerful Presentations with or without Slides Bisher besters Buch von Garr. Und das will [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=splitshade.wordpress.com&amp;blog=5189437&amp;post=779&amp;subd=splitshade&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Hi,</p>
<p>das Jahr ist zwar noch nicht vorüber, trotzdem möchte ich euch schonmal meine Top-10 Bücher 2011 vorstellen.</p>
<p><a href="http://www.amazon.de/Pragmatic-Thinking-Learning-Refactor-Programmers/dp/1934356050/ref=sr_1_1?ie=UTF8&amp;qid=1322166540&amp;sr=8-1">Pragmatic THinking and Learning</a></p>
<div style="overflow:auto;"><img class="alignnone" src="http://ecx.images-amazon.com/images/I/51xArZnegaL._SL500_AA300_.jpg" alt="" width="300" height="300" /></div>
<p>Das Buch ist spitze. Das Buch hat es tatsächlich geschafft, mich zu inspirieren. Totale Leseempfehlung.</p>
<p><a href="http://www.amazon.de/Naked-Presenter-Delivering-Powerful-Presentations/dp/0321704452/ref=sr_1_1?s=books-intl-de&amp;ie=UTF8&amp;qid=1322166884&amp;sr=1-1"><br />
The Naked Presenter: Delivering Powerful Presentations with or without Slides</a></p>
<p><img class="alignnone" src="http://splitshade.files.wordpress.com/2011/11/naked_presenter_lge.jpg?w=305&#038;h=305" alt="" width="305" height="305" /></p>
<p>Bisher besters Buch von Garr. Und das will was heißen.</p>
<p><a href="http://www.amazon.de/Steve-Jobs-Biography-Walter-Isaacson/dp/1451648537/ref=sr_1_1?s=books-intl-de&amp;ie=UTF8&amp;qid=1322167078&amp;sr=1-1">Steve Jobs &#8211; A Biography</a></p>
<p><img class="alignnone" src="http://ecx.images-amazon.com/images/I/51OVbuvFLDL._SL500_AA300_.jpg" alt="" width="300" height="300" /></p>
<p>Ob man Steve Jobs mag oder nicht, das Buch ist eine definitive Lesempfehlung. Man erfährt viel über Apple und Steve, aber mindestens eben so viel über Design und worauf es wirklich ankommt. Das Buch hat mich tief beeindruckt.</p>
<p><a href="http://www.amazon.de/Confessions-Public-Speaker-Scott-Berkun/dp/1449301959/ref=sr_1_1?s=books-intl-de&amp;ie=UTF8&amp;qid=1322167192&amp;sr=1-1">Confessions of a Public Speaker</a></p>
<p><img class="alignnone" src="http://www.thespeakerpoint.com/wp-content/uploads/2011/02/confessions-of-a-public-speaker.png" alt="" width="336" height="504" /></p>
<p>Man merkt, dass Scott Berkun weiß, wovon er spricht. Ich habe selten ein so amüsant zu lesendes Buch in der Hand gehabt. Definitive Kaufempfehlung.</p>
<p><a href="http://www.amazon.de/Coding-Jonathan-Locke/dp/0615404820/ref=sr_1_1?s=books-intl-de&amp;ie=UTF8&amp;qid=1322167319&amp;sr=1-1">Coding</a></p>
<p><img class="alignnone" src="http://ecx.images-amazon.com/images/I/41e8kPxx3ML._SL500_AA300_.jpg" alt="" width="300" height="300" /></p>
<p>Eines der besten Softwareenticklungsbücher die ich bisher gelesen habe, kurz prägnant auf den Punkt. Ich hab das Buch schon zweimal gelesen und kann nur dringend empfehlen, hier einen Blick rein zu werfen.</p>
<p><a href="http://www.amazon.de/Clean-Coder-Conduct-Professional-Programmers/dp/0137081073/ref=sr_1_1?s=books-intl-de&amp;ie=UTF8&amp;qid=1322167444&amp;sr=1-1">Clean Coder</a></p>
<p><img class="alignnone" src="http://www.jpc.de/image/w600/front/0/9780137081073.jpg" alt="" width="314" height="420" /></p>
<p>Zu Uncle Bob Martin muss man nichts sagen. Das Buch sollte jeder unter sein Kopfkissen legen. Echt jetzt!!</p>
<p><a href="http://www.amazon.de/Things-Every-Programmer-Should-Know/dp/0596809484/ref=sr_1_1?s=books-intl-de&amp;ie=UTF8&amp;qid=1322167566&amp;sr=1-1">97 Things every Programmer should know</a></p>
<p><img class="alignnone" src="http://splitshade.files.wordpress.com/2011/11/97thingseveryprogrammershouldknowbykevlinhenney.jpg?w=276&#038;h=400" alt="" width="276" height="400" /></p>
<p>Sehr amüsant und lehrreich.</p>
<p><a href="http://www.amazon.de/Presentation-Zen-Design-Principles-Presentations/dp/0321668790/ref=sr_1_1?s=books-intl-de&amp;ie=UTF8&amp;qid=1322167726&amp;sr=1-1"><br />
Presentation Zen Design: Simple Design Principles and Techniques to Enhance Your Presentations</a></p>
<p><img class="alignnone" src="http://www.presentationzen.com/.a/6a00d83451b64669e2011570cd4ded970b-200wi" alt="" width="200" height="240" /></p>
<p>Garr Reynolds in Hochform. Spitzenbuch!</p>
<p><a href="http://www.amazon.de/Your-Brain-Work-Strategies-Distraction/dp/0061771295/ref=sr_1_1?s=books-intl-de&amp;ie=UTF8&amp;qid=1322168003&amp;sr=1-1">Your Brain at work</a></p>
<p><img class="alignnone" src="http://www.briefcoachingsolutions.com/wp-content/uploads/2010/10/your-brain-at-work.jpg" alt="" width="224" height="297" /></p>
<p>Hochinteressant und amüsant geschrieben. Das Buch ist echt lesenswert.</p>
<p><a href="http://www.amazon.de/Founders-Work-Stories-Startups-Problem-Solution/dp/1430210788/ref=sr_1_1?s=books-intl-de&amp;ie=UTF8&amp;qid=1322168204&amp;sr=1-1">Founders at work</a></p>
<p><img class="alignnone" src="http://pradeepc.files.wordpress.com/2007/07/founders-at-work.jpg?w=217&#038;h=310" alt="" width="217" height="310" /></p>
<p>Hochinteressante Geschichten &#8211; lesenswert.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/splitshade.wordpress.com/779/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/splitshade.wordpress.com/779/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/splitshade.wordpress.com/779/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/splitshade.wordpress.com/779/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/splitshade.wordpress.com/779/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/splitshade.wordpress.com/779/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/splitshade.wordpress.com/779/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/splitshade.wordpress.com/779/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/splitshade.wordpress.com/779/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/splitshade.wordpress.com/779/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/splitshade.wordpress.com/779/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/splitshade.wordpress.com/779/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/splitshade.wordpress.com/779/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/splitshade.wordpress.com/779/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=splitshade.wordpress.com&amp;blog=5189437&amp;post=779&amp;subd=splitshade&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://splitshade.wordpress.com/2011/11/24/top-10-bucher-die-mich-dieses-jahr-inspiriert-haben/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0f446b406cac4629cd7ddf73607054b5?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">splitshade</media:title>
		</media:content>

		<media:content url="http://ecx.images-amazon.com/images/I/51xArZnegaL._SL500_AA300_.jpg" medium="image" />

		<media:content url="http://splitshade.files.wordpress.com/2011/11/naked_presenter_lge.jpg?w=300" medium="image" />

		<media:content url="http://ecx.images-amazon.com/images/I/51OVbuvFLDL._SL500_AA300_.jpg" medium="image" />

		<media:content url="http://www.thespeakerpoint.com/wp-content/uploads/2011/02/confessions-of-a-public-speaker.png" medium="image" />

		<media:content url="http://ecx.images-amazon.com/images/I/41e8kPxx3ML._SL500_AA300_.jpg" medium="image" />

		<media:content url="http://www.jpc.de/image/w600/front/0/9780137081073.jpg" medium="image" />

		<media:content url="http://splitshade.files.wordpress.com/2011/11/97thingseveryprogrammershouldknowbykevlinhenney.jpg?w=207" medium="image" />

		<media:content url="http://www.presentationzen.com/.a/6a00d83451b64669e2011570cd4ded970b-200wi" medium="image" />

		<media:content url="http://www.briefcoachingsolutions.com/wp-content/uploads/2010/10/your-brain-at-work.jpg" medium="image" />

		<media:content url="http://pradeepc.files.wordpress.com/2007/07/founders-at-work.jpg" medium="image" />
	</item>
		<item>
		<title>Besser Gits Nicht &#8211; Git Artikel im Java Magazin</title>
		<link>http://splitshade.wordpress.com/2011/11/11/besser-gits-nicht-git-artikel-im-java-magazin/</link>
		<comments>http://splitshade.wordpress.com/2011/11/11/besser-gits-nicht-git-artikel-im-java-magazin/#comments</comments>
		<pubDate>Fri, 11 Nov 2011 10:04:24 +0000</pubDate>
		<dc:creator>splitshade</dc:creator>
				<category><![CDATA[git]]></category>

		<guid isPermaLink="false">http://splitshade.wordpress.com/?p=771</guid>
		<description><![CDATA[Hallo, wie bereits angedroht ist im aktuellen Java Magazin ein Artikel von mir erschienen, der auch hier hier gelesen werden kann. Da ich leider heute krank im Bett liege habe ich die Zeit genutzt, diesen nochmal zu lesen. Ich finde, er ist sehr lesenswert. Viel Spaß damit.<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=splitshade.wordpress.com&amp;blog=5189437&amp;post=771&amp;subd=splitshade&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><a href="http://splitshade.files.wordpress.com/2011/11/intro.jpg"><img class="aligncenter size-full wp-image-773" title="intro" src="http://splitshade.files.wordpress.com/2011/11/intro.jpg?w=600&#038;h=453" alt="" width="600" height="453" /></a></p>
<p>Hallo,</p>
<p>wie bereits <a title="Git Artikel im nächsten Java Magazin" href="http://splitshade.wordpress.com/2011/09/29/git-artikel-im-nachsten-java-magazin/">angedroht</a> ist im aktuellen Java Magazin ein Artikel von mir erschienen, der auch hier<a href="http://splitshade.files.wordpress.com/2011/11/jm12_11_dilger_git.pdf"> hier</a> gelesen werden kann.</p>
<p>Da ich leider heute krank im Bett liege habe ich die Zeit genutzt, diesen nochmal zu lesen. Ich finde, er ist sehr lesenswert.</p>
<p>Viel Spaß damit.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/splitshade.wordpress.com/771/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/splitshade.wordpress.com/771/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/splitshade.wordpress.com/771/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/splitshade.wordpress.com/771/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/splitshade.wordpress.com/771/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/splitshade.wordpress.com/771/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/splitshade.wordpress.com/771/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/splitshade.wordpress.com/771/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/splitshade.wordpress.com/771/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/splitshade.wordpress.com/771/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/splitshade.wordpress.com/771/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/splitshade.wordpress.com/771/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/splitshade.wordpress.com/771/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/splitshade.wordpress.com/771/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=splitshade.wordpress.com&amp;blog=5189437&amp;post=771&amp;subd=splitshade&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://splitshade.wordpress.com/2011/11/11/besser-gits-nicht-git-artikel-im-java-magazin/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0f446b406cac4629cd7ddf73607054b5?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">splitshade</media:title>
		</media:content>

		<media:content url="http://splitshade.files.wordpress.com/2011/11/intro.jpg" medium="image">
			<media:title type="html">intro</media:title>
		</media:content>
	</item>
		<item>
		<title>Wicket, Ajax und AjaxRequestTargets &#8211; onAfterAjaxRequest</title>
		<link>http://splitshade.wordpress.com/2011/10/26/wicket-ajax-und-ajaxrequesttargets-onafterajaxrequest/</link>
		<comments>http://splitshade.wordpress.com/2011/10/26/wicket-ajax-und-ajaxrequesttargets-onafterajaxrequest/#comments</comments>
		<pubDate>Wed, 26 Oct 2011 20:08:29 +0000</pubDate>
		<dc:creator>splitshade</dc:creator>
				<category><![CDATA[cool eclipse]]></category>

		<guid isPermaLink="false">http://splitshade.wordpress.com/?p=766</guid>
		<description><![CDATA[Hallo zusammen, oft gibt es eine Anforderung, nach jedem AjaxRequest beispielsweise ein Javascript an den Client zu senden (beispielsweise für Tracking, Logging etc..) Man kann sich hier verkünsteln, aber Wicket macht es einem sehr einfach: In der WebApplication kann folgendes überschrieben werden: Damit hat man einen Listener, der sowohl vor als auch nach jedem AjaxRequest [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=splitshade.wordpress.com&amp;blog=5189437&amp;post=766&amp;subd=splitshade&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Hallo zusammen,</p>
<p>oft gibt es eine Anforderung, nach jedem AjaxRequest beispielsweise ein Javascript an den Client zu senden (beispielsweise für Tracking, Logging etc..)</p>
<p>Man kann sich hier verkünsteln, aber Wicket macht es einem sehr einfach:</p>
<p>In der WebApplication kann folgendes überschrieben werden:</p>
<p><pre class="brush: java;">

public void init() {
super.init();
getAjaxRequestTargetListeners().add(new IListener() {

public void onBeforeRespond(Map&lt;String, Component&gt; map,
AjaxRequestTarget target) {
String values = &quot;&quot;;
Iterator&lt;String&gt; it = map.keySet().iterator();
while (it.hasNext()) {
values += &quot;, &quot; + it.next();
}
target.appendJavaScript(&quot;alert('Before AjaxRequest Target Responds - &quot; + values + &quot;')&quot;);

}

public void onAfterRespond(Map&lt;String, Component&gt; map,
IJavaScriptResponse response) {
String values = &quot;&quot;;
Iterator&lt;String&gt; it = map.keySet().iterator();
while (it.hasNext()) {
values += &quot;, &quot; + it.next();
}
response.addJavaScript(&quot;alert('onAfterRespond Responds - &quot; + values+&quot;')&quot;);
}
});

// add your configuration here
}

</pre></p>
<p>Damit hat man einen Listener, der sowohl vor als auch nach jedem AjaxRequest ausgeführt wird, und man hat zu jedem Zeitpunkt die Möglichkeit, Javascript an den Client zu schicken.</p>
<p>Obendrein bekommt man von Wicket noch eine Map mit allen Komponenten übergeben, die dem AjaxRequestTarget hinzugefügt worden sind.</p>
<p><a href="http://splitshade.files.wordpress.com/2011/10/s1.png"><img class="aligncenter size-full wp-image-767" title="s1" src="http://splitshade.files.wordpress.com/2011/10/s1.png?w=600" alt=""   /></a></p>
<p><a href="http://splitshade.files.wordpress.com/2011/10/s2.png"><img class="aligncenter size-full wp-image-768" title="s2" src="http://splitshade.files.wordpress.com/2011/10/s2.png?w=600" alt=""   /></a></p>
<p>Übrigens, nur nebenbei aber richtig gut &#8211; AjaxRequestTargets kann man überall in der Applikation ermitteln, und zwar mit</p>
<p><pre class="brush: java;">

AjaxRequestTarget.get()

</pre></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/splitshade.wordpress.com/766/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/splitshade.wordpress.com/766/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/splitshade.wordpress.com/766/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/splitshade.wordpress.com/766/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/splitshade.wordpress.com/766/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/splitshade.wordpress.com/766/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/splitshade.wordpress.com/766/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/splitshade.wordpress.com/766/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/splitshade.wordpress.com/766/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/splitshade.wordpress.com/766/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/splitshade.wordpress.com/766/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/splitshade.wordpress.com/766/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/splitshade.wordpress.com/766/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/splitshade.wordpress.com/766/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=splitshade.wordpress.com&amp;blog=5189437&amp;post=766&amp;subd=splitshade&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://splitshade.wordpress.com/2011/10/26/wicket-ajax-und-ajaxrequesttargets-onafterajaxrequest/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0f446b406cac4629cd7ddf73607054b5?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">splitshade</media:title>
		</media:content>

		<media:content url="http://splitshade.files.wordpress.com/2011/10/s1.png" medium="image">
			<media:title type="html">s1</media:title>
		</media:content>

		<media:content url="http://splitshade.files.wordpress.com/2011/10/s2.png" medium="image">
			<media:title type="html">s2</media:title>
		</media:content>
	</item>
		<item>
		<title>Sehr guter Wicket Artikel</title>
		<link>http://splitshade.wordpress.com/2011/10/23/sehr-guter-wicket-artikel/</link>
		<comments>http://splitshade.wordpress.com/2011/10/23/sehr-guter-wicket-artikel/#comments</comments>
		<pubDate>Sun, 23 Oct 2011 13:01:34 +0000</pubDate>
		<dc:creator>splitshade</dc:creator>
				<category><![CDATA[Wicket]]></category>

		<guid isPermaLink="false">http://splitshade.wordpress.com/?p=760</guid>
		<description><![CDATA[Und zwar hier, der Teil über Session-Size sollte sich jeder zu Gemüte führen. Anbei sei hier nochmal auf meine Wicket-Coding Guidelines verwiesen, zusammen mit diesen beiden Artikeln solltet ihr ziemlich schnell funktionale, performante und lesbare Wicket-Applikationen schreiben können:).<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=splitshade.wordpress.com&amp;blog=5189437&amp;post=760&amp;subd=splitshade&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Und zwar <a href="http://www.small-improvements.com/10-things-about-apache-wicket-i-love">hier</a>, der Teil über Session-Size sollte sich jeder zu Gemüte führen.</p>
<p>Anbei sei hier nochmal auf meine <a href="http://splitshade.wordpress.com/2011/06/02/wicket-developer-guidelines/">Wicket-Coding Guidelines</a> verwiesen, zusammen mit diesen beiden Artikeln solltet ihr ziemlich schnell funktionale, performante und lesbare Wicket-Applikationen schreiben können:).</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/splitshade.wordpress.com/760/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/splitshade.wordpress.com/760/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/splitshade.wordpress.com/760/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/splitshade.wordpress.com/760/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/splitshade.wordpress.com/760/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/splitshade.wordpress.com/760/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/splitshade.wordpress.com/760/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/splitshade.wordpress.com/760/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/splitshade.wordpress.com/760/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/splitshade.wordpress.com/760/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/splitshade.wordpress.com/760/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/splitshade.wordpress.com/760/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/splitshade.wordpress.com/760/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/splitshade.wordpress.com/760/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=splitshade.wordpress.com&amp;blog=5189437&amp;post=760&amp;subd=splitshade&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://splitshade.wordpress.com/2011/10/23/sehr-guter-wicket-artikel/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0f446b406cac4629cd7ddf73607054b5?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">splitshade</media:title>
		</media:content>
	</item>
		<item>
		<title>Präsentationen erfolgreich vorbereiten &#8211; Schritt 1 &#8211; Brainstorming</title>
		<link>http://splitshade.wordpress.com/2011/10/08/prasentationen-erfolgreich-vorbereiten-schritt-1-brainstorming/</link>
		<comments>http://splitshade.wordpress.com/2011/10/08/prasentationen-erfolgreich-vorbereiten-schritt-1-brainstorming/#comments</comments>
		<pubDate>Sat, 08 Oct 2011 16:44:49 +0000</pubDate>
		<dc:creator>splitshade</dc:creator>
				<category><![CDATA[Presentation Art]]></category>

		<guid isPermaLink="false">http://splitshade.wordpress.com/?p=749</guid>
		<description><![CDATA[Hallo zusammen, da ich momentan gerade eine ganze Menge verschiedener Workshops vorbereite, stelle ich hier Schritt für Schritt vor, wie genau ich dabei vorgehe. Zunächst mal bleibe ich weit weg von jedem Rechner und jeder Präsentationssoftware (welche Software ich einsetze etc., dazu später). Das Thema ist meist ja bereits vorgegeben, nicht jedoch, wie ein bestimmtes [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=splitshade.wordpress.com&amp;blog=5189437&amp;post=749&amp;subd=splitshade&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Hallo zusammen,</p>
<p>da ich momentan gerade eine ganze Menge verschiedener Workshops vorbereite, stelle ich hier Schritt für Schritt vor, wie genau ich dabei vorgehe.</p>
<p>Zunächst mal bleibe ich weit weg von jedem Rechner und jeder Präsentationssoftware (welche Software ich einsetze etc., dazu später).</p>
<p>Das Thema ist meist ja bereits vorgegeben, nicht jedoch, wie ein bestimmtes Thema präsentiert werden soll, auch welche Art und Weise gearbeitet werden soll. Wenn ich anfange, ist mein Kopf meistens recht leer und ich weiß nicht so recht, wie ich anfangen soll.</p>
<p>Eine wirklich wunderbare Technik, um diese Leere mit Inhalt zu füllen ist Brainstorming, bzw. das Erstellen einer Mindmap. Wie eine solche Mindmap aussehen kann, seht ihr im folgenden Bild.</p>
<p>Ich schließe mich also zunächst für 3-4 Stunden in einem Zimmer ein und Erstelle die initiale Grundidee.</p>
<p><a href="http://splitshade.files.wordpress.com/2011/10/git-workshop-mindmap.png"><img class="aligncenter size-full wp-image-750" title="git-workshop-mindmap" src="http://splitshade.files.wordpress.com/2011/10/git-workshop-mindmap.png?w=600&#038;h=426" alt="" width="600" height="426" /></a></p>
<p>Was aus dieser Grundidee entstehen kann wird im nächsten Teil erklärt.</p>
<p>Diese Technik hat noch niemals nicht funktioniert, also ein Versuch ist es zumindest wert. Diese Technik läßt sich nicht nur für das Vorbereiten von Präsentationen verwenden.</p>
<p>Wie geht ihr denn die Problematik an? Über Rückmeldungen würde ich mich freuen.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/splitshade.wordpress.com/749/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/splitshade.wordpress.com/749/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/splitshade.wordpress.com/749/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/splitshade.wordpress.com/749/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/splitshade.wordpress.com/749/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/splitshade.wordpress.com/749/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/splitshade.wordpress.com/749/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/splitshade.wordpress.com/749/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/splitshade.wordpress.com/749/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/splitshade.wordpress.com/749/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/splitshade.wordpress.com/749/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/splitshade.wordpress.com/749/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/splitshade.wordpress.com/749/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/splitshade.wordpress.com/749/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=splitshade.wordpress.com&amp;blog=5189437&amp;post=749&amp;subd=splitshade&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://splitshade.wordpress.com/2011/10/08/prasentationen-erfolgreich-vorbereiten-schritt-1-brainstorming/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0f446b406cac4629cd7ddf73607054b5?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">splitshade</media:title>
		</media:content>

		<media:content url="http://splitshade.files.wordpress.com/2011/10/git-workshop-mindmap.png" medium="image">
			<media:title type="html">git-workshop-mindmap</media:title>
		</media:content>
	</item>
		<item>
		<title>Git Artikel im nächsten Java Magazin</title>
		<link>http://splitshade.wordpress.com/2011/09/29/git-artikel-im-nachsten-java-magazin/</link>
		<comments>http://splitshade.wordpress.com/2011/09/29/git-artikel-im-nachsten-java-magazin/#comments</comments>
		<pubDate>Thu, 29 Sep 2011 06:25:15 +0000</pubDate>
		<dc:creator>splitshade</dc:creator>
				<category><![CDATA[Fachartikel]]></category>
		<category><![CDATA[git]]></category>

		<guid isPermaLink="false">http://splitshade.wordpress.com/?p=649</guid>
		<description><![CDATA[Hallo zusammen, im nächsten Java Magazin wird ein Artikel von mir zum Thema GIT erscheinen mit dem Titel &#8222;Besser Gits nicht!&#8220; Der Artikel ist inhaltlich relativ locker, aber ich hoffe lesenswert geschrieben. Ich freue mich über Kommentare.<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=splitshade.wordpress.com&amp;blog=5189437&amp;post=649&amp;subd=splitshade&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Hallo zusammen,<br />
im nächsten Java Magazin wird ein Artikel von mir zum Thema GIT erscheinen mit dem Titel &#8222;Besser Gits nicht!&#8220;</p>
<p>Der Artikel ist inhaltlich relativ locker, aber ich hoffe lesenswert geschrieben.</p>
<p>Ich freue mich über Kommentare.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/splitshade.wordpress.com/649/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/splitshade.wordpress.com/649/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/splitshade.wordpress.com/649/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/splitshade.wordpress.com/649/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/splitshade.wordpress.com/649/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/splitshade.wordpress.com/649/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/splitshade.wordpress.com/649/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/splitshade.wordpress.com/649/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/splitshade.wordpress.com/649/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/splitshade.wordpress.com/649/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/splitshade.wordpress.com/649/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/splitshade.wordpress.com/649/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/splitshade.wordpress.com/649/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/splitshade.wordpress.com/649/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=splitshade.wordpress.com&amp;blog=5189437&amp;post=649&amp;subd=splitshade&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://splitshade.wordpress.com/2011/09/29/git-artikel-im-nachsten-java-magazin/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0f446b406cac4629cd7ddf73607054b5?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">splitshade</media:title>
		</media:content>
	</item>
		<item>
		<title>Ajax mit Wicket &#8211; Wie funktionierts?</title>
		<link>http://splitshade.wordpress.com/2011/09/22/ajax-mit-wicket-wie-funktionierts/</link>
		<comments>http://splitshade.wordpress.com/2011/09/22/ajax-mit-wicket-wie-funktionierts/#comments</comments>
		<pubDate>Thu, 22 Sep 2011 20:04:59 +0000</pubDate>
		<dc:creator>splitshade</dc:creator>
				<category><![CDATA[Wicket]]></category>

		<guid isPermaLink="false">http://splitshade.wordpress.com/?p=648</guid>
		<description><![CDATA[Mit Wicket 1.5 ist es so einfach wie nie, Ajax basierte Webapplikationen zu erstellen. Wie einfach das geht und wieviel Spaß das machen kann will dieser Artikel zeigen. Zunächst erzeugen wir uns eine sehr einfache Wicket-Applikation: mit der Nummer 217. Anschließend passen wir die Version in der pom noch an (im Moment wird über den [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=splitshade.wordpress.com&amp;blog=5189437&amp;post=648&amp;subd=splitshade&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><img class="alignnone" title="wicket" src="http://svn.apache.org/repos/asf/wicket/sandbox/dashorst/animation/logo-top.png" alt="" width="238" height="237" /></p>
<p>Mit Wicket 1.5 ist es so einfach wie nie, Ajax basierte Webapplikationen zu erstellen.</p>
<p>Wie einfach das geht und wieviel Spaß das machen kann will dieser Artikel zeigen.</p>
<p>Zunächst erzeugen wir uns eine sehr einfache Wicket-Applikation:</p>
<p><pre class="brush: plain;">

mvn archetype generate

</pre></p>
<p>mit der Nummer 217.</p>
<p>Anschließend passen wir die Version in der pom noch an (im Moment wird über den Maven Archetype die Version 1.5.0 noch nicht angeboten.</p>
<p>Hier ist das Gradle-Build File (es gibt aber auch ein Maven Pom):</p>
<p><pre class="brush: plain;">

apply plugin: 'java'
apply plugin: 'eclipse'

defaultTasks &quot;build&quot;

version = &quot;1.0-SNAPSHOT&quot;

springVersion = '3.0.5.RELEASE'
wicketVersion = '1.5.0'
jettyVersion = '7.3.0.v20110203'

sourceCompatibility = 1.6
targetCompatibility = 1.6

dependencies {
compile  &quot;org.apache.wicket:wicket:$wicketVersion&quot;
compile  &quot;org.apache.wicket:wicket-extensions:$wicketVersion&quot;
compile  &quot;org.apache.wicket:wicket-spring:$wicketVersion&quot;
compile  &quot;org.apache.wicket:wicket-datetime:$wicketVersion&quot;
compile  'org.slf4j:slf4j-log4j12:1.5.8'
compile  &quot;org.springframework:spring-core:$springVersion&quot;
compile  &quot;org.springframework:spring-beans:$springVersion&quot;
compile  &quot;org.springframework:spring-jdbc:$springVersion&quot;
compile  &quot;org.springframework:spring-web:$springVersion&quot;
compile  &quot;org.springframework:spring-orm:$springVersion&quot;
compile  &quot;org.springframework:spring-test:$springVersion&quot;
testCompile     &quot;junit:junit:4.8.1&quot;
testCompile     &quot;org.mockito:mockito-core:1.8.5&quot;
testCompile &quot;org.eclipse.jetty.aggregate:jetty-all-server:$jettyVersion&quot;

}

sourceSets {
main {
resources {
srcDir 'src/main/resources'
srcDir 'src/main/java'
}
}
test {
resources {
srcDir 'src/test/resources'
srcDir 'src/test/java'
}
}
}

repositories {
mavenCentral()
}

</pre></p>
<p>Zunächst räumen wir die Applikation noch ein wenig auf, damit wir wirklich &#8222;auf der grünen Wiese&#8220; anfangen können.<br />
Die Page sollte so aussehen:</p>
<p><pre class="brush: java;">
public class HomePage extends WebPage {
private static final long serialVersionUID = 1L;

public HomePage(final PageParameters parameters) {
}
}
</pre></p>
<p>Anschließend löschen wir noch die Klasse &#8222;TestHomePage&#8220; unter src/test/java, Testen kann hier nicht das Thema.</p>
<p>Zunächst mal schauen wir uns grundsätzlich an, wie Wicket im Zusammenspiel mit Ajax überhaupt funktioniert.</p>
<p>Im nächsten Schritt werden wir einige Funktionale Elemente einbauen (TextFelder etc,)</p>
<p>Anschließend werden wir uns die Integration mit der meiner Ansicht nach coolsten Ajax-Engine die aktuell verfügbar ist anschauen.</p>
<p>Anschließend werden wir einen Blick auf den neuen Wicket Event Mechanismus werfen.</p>
<p>Der Source-Code ist übrigens verfügbar, und zwar hier. Alle wichtigen Schritte sind jeweils getaggt. Ich werde im Artikel darauf verweisen.</p>
<p>Im Package &#8222;src/test/java&#8220; befindet sich übrigens die Klasse Start, diese hat eine main()-Methode und startet einen Embedded-Jetty, d.h. die Applikation ist direkt aus Eclipse heraus startbar.</p>
<p>Schritt 1 &#8211; die Wicket Ajax Engine</p>
<p>Wicket ist ein etabliertes Webframework und kommt mit einer schlanken aber brauchbaren Ajax-Engine daher.</p>
<p>Was bietet die Wicket Ajax Engine?</p>
<p>Abstraktion von Browser-Inkompatibilitäten<br />
Abstraktion der Ajax-Requests<br />
Parallele / Synchrone Verarbeitung von Ajax-Requests</p>
<p>Betrachten wir doch mal, wie die AjaxEngine grundsätzlich aufgebaut ist. Hierfür fügen wir in die Form einen einfachen AjaxLink ein.</p>
<p>Wicket bietet von Haus aus schon eine ganze Menge an Komponenten, die Ajax-Funktionalität Out-of-the-Box mitbringen. Der Ajax-Link ist eine davon &#8211; Ein Link der einen Ajax-Request an den Server sendet.</p>
<p>Folgendes Fragment bauen wir in das Html der Seite ein.</p>
<p><pre class="brush: xml;">

</pre></p>
<p>Im Java Code das Pendant dazu.</p>
<p><pre class="brush: java;">

add(new AjaxLink(&quot;ajaxLink&quot;){
@Override
public void onClick(AjaxRequestTarget target) {
target.appendJavaScript(&quot;alert('hello world!');&quot;);
}
});

</pre></p>
<p>Die Implementierung spielt momentan keine Rolle, dazu kommen wir später noch. Zunächst mal wollen wir uns anschauen, was Wicket uns generiert hat.<br />
Hierzu betrachten wir den Quellcode der generierten Webseite.</p>
<p><pre class="brush: java;">
&lt;a id=&quot;ajaxLink1&quot; onclick=&quot;var wcall=wicketAjaxGet('wicket/page?0-1.IBehaviorListener.0-ajaxLink',function() { }.bind(this),function() { }.bind(this), function() {return Wicket.$('ajaxLink1') != null;}.bind(this));return !wcall;&quot; href=&quot;&lt;a href=&quot;&gt;Click me&lt;/a&gt;
</pre></p>
<p>Besonders interessant ist natürlich der onclick-Handler des Links:</p>
<p><pre class="brush: jscript;">
var wcall=wicketAjaxGet('wicket/page?0-1.IBehaviorListener.0-ajaxLink',function() { }.bind(this),function() { }.bind(this), function() {return Wicket.$('ajaxLink1') != null;}.bind(this));return !wcall;&quot;
</pre></p>
<p>Um zu verstehen, was das bedeutet betrachten wir uns gleichzeitig die Implementierung der entsprechenden Stelle in den Wicket-Sources.<br />
Die Javascript Implementierung befindet sich im Modul wicket-core in der Datei wicket-ajax.js.</p>
<p><pre class="brush: jscript;">
function wicketAjaxGet(url, successHandler, failureHandler, precondition, channel) {

var call = new Wicket.Ajax.Call(url, successHandler, failureHandler, channel);

if (typeof(precondition) != &quot;undefined&quot; &amp;&amp; precondition != null) {
call.request.precondition = precondition;
}

return call.call();
}
</pre></p>
<p>Die wicketAjaxGet-Routine hat also folgende Parameter:</p>
<p><pre class="brush: jscript;">
url, successHandler, failureHandler, channel
</pre></p>
<p>Die Parameter sind folgendermaßen belegt:</p>
<p><pre class="brush: java;">
url : wicket/page?0-1.IBehaviorListener.0-ajaxLink
successHandler : function() { }.bind(this)
failureHandler :function() { }.bind(this)
channel :function() {return Wicket.$('ajaxLink1') != null;}.bind(this));
</pre></p>
<p>Ok, schauen wir uns ein wenig genauer an, wie der Wicket-Ajax-Mechanismus überhaupt funktioniert.<br />
Die Url wicket/page?0-1.IBehaviorListener.0-ajaxLink adressiert ein AjaxBehavior.</p>
<p>Wicket Behaviors bieten die einfache Möglichkeit, zusätzliches Verhalten für Wicket-Komponenten zu definieren.<br />
Im folgenden Code-Schnipsel wird das grob veranschaulicht.<br />
Zunächst definieren wir im Html ein einfaches div-Element zur Anzeige eines Textes.</p>
<p><pre class="brush: xml;">
</pre></p>
<p>und zusätzlich folgenden Java-Code:</p>
<p><pre class="brush: java;">
Label label = new Label(&quot;ajaxText&quot;,&quot;Ajax Clickable Text&quot;);
add(label);
label.add(new AjaxEventBehavior(&quot;onclick&quot;){

@Override
protected void onEvent(AjaxRequestTarget target) {
target.appendJavaScript(&quot;alert('clicked')&quot;);
}});
</pre></p>
<p>Auf diese Art und Weise kann praktisch jedes Element ajaxifiziert werden.<br />
Wie aber kommt man jetzt vom Javascript auf der Clientseite zum Serverseitigen Code?</p>
<p>Ganz einfach, über die URL.</p>
<p><pre class="brush: jscript;">
wicket/page?0-1.IBehaviorListener.0-ajaxLink
</pre></p>
<p>Hiermit wird die PageMap 0 adressiert, in dieser PageMap die Page mit der Version 1. Adressiert wird ein IBehaviorListener, und zwar<br />
mit der Version 0 das auf der Komponente mit der ID &#8222;ajaxLink&#8220; liegt.<br />
Wenn euch genauer interessiert, wie diese URL geparsed wird, könnt ihr beispielsweise die Klasse PageInstanceMapper genauer unter die Lupe<br />
nehmen.</p>
<p>Das Schema einer URL ist in der Klasse URL definiert (natürlch die in den wicket-packages&#8230;)</p>
<p>Hier wird beispielsweise auch aus dem String IBehaviorListener die entsprechende Klasse erzeugt, das Mapping hierzu findet ihr in der KLasse<br />
RequestListenerInterface.</p>
<p>Anschließend wird in der Klasse ListenerInterfaceRequestHandler die eigentliche Requestverarbeitung angestossen.</p>
<p>Ok, aber das könnt ihr alles selber sehen, wenn ihr einfach mal den Debugger anschmeißt und schaut, was passiert. Ich kann das nur empfehlen, ist wirklich hochinteressant.</p>
<p>Ok, lange Rede kurzer Sinn, was Wicket macht, wenn man diese URL aufruft (die man übrigens auch problemlos einfach im Browser aufrufen könnte), es mappt den Request in ein AjaxRequestTarget.</p>
<p>Überhaupt lohnt sich ein etwas genauerer Blick in die Klasse RequestListenerInterface und in die Klasse RequestCycle, da hier viel passiert und man sich relativ schnell ein Verständnis aufbauen kann, wie die Requestverarbeitung in Wicket funktioniert.</p>
<p>Nochmal zur Erinnerung die RequestParameter:</p>
<p><pre class="brush: java;">
url : wicket/page?0-1.IBehaviorListener.0-ajaxLink
successHandler : function() { }.bind(this)
failureHandler :function() { }.bind(this)
channel :function() {return Wicket.$('ajaxLink1') != null;}.bind(this));
</pre></p>
<h2>Wicket Ajax Success &#8211; bzw. FailureHandler</h2>
<p>SuccessHandler ist leer, d.h. es gibt keine bestimmte AKtion, wenn der Ajax-Requets erfolgreich ist.</p>
<p>Das Gleiche gilt für den Failure-Handler, sollte der Ajax Request fehlschlagen, dann schlägt der AjaxRequest eben fehl.<br />
Ich hatte das Problem schon mehrfach in diversen Projekten, dass die Infrastruktur uns einen Strich durch die Rechnung macht -<br />
beispielsweise Firewalls, Loadbalancer etc., in diesen Fällen wird der FailureHandler plötzlich sehr interessant.</p>
<p>Wie aber kann ich als Entwickler jetzt diese Success- bzw. FailureHandler setzen.</p>
<p>Hierzu schauen wir uns kurz mal die Klasse AbstractDefaultAjaxRequestTarget an.</p>
<p><pre class="brush: java;">
/**
* @return javascript that will run when the ajax call finishes with an error status
*/
protected CharSequence getFailureScript()
{
return null;
}

/**
* @return javascript that will run when the ajax call finishes successfully
*/
protected CharSequence getSuccessScript()
{
return null;
}

</pre></p>
<p>Das sollte uns jetzt schon bekannt vorkommen.<br />
Wo wird das aber nun aufgerufen?</p>
<p>Hierzu schaut ihr euch am besten in AbstractDefaultAjaxBehavior mal die Methode</p>
<p><pre class="brush: java;">
protected CharSequence generateCallbackScript(final CharSequence partialCall)
</pre></p>
<p>an.</p>
<p>Am besten wirds sein, wir implementieren einfach mal den Success- bzw. auch den FailureHandler.<br />
Wir haben noch das AjaxEventBehavior von vorhin.<br />
Hier implementieren wir noch die zuvor erwähnten Methoden.</p>
<p><pre class="brush: java;">
label.add(new AjaxEventBehavior(&quot;onclick&quot;){

@Override
protected void onEvent(AjaxRequestTarget target) {
target.appendJavaScript(&quot;alert('clicked')&quot;);
}

@Override
protected CharSequence getFailureScript() {
return &quot;alert('there was a failure!!')&quot;;
}

@Overridearauf
protected CharSequence getSuccessScript() {
return &quot;alert('Ajax call was successful')&quot;;
}
});
</pre></p>
<p><a href="http://splitshade.files.wordpress.com/2011/09/successful_ajax_call.png"><img class="aligncenter size-full wp-image-672" title="successful_ajax_call" src="http://splitshade.files.wordpress.com/2011/09/successful_ajax_call.png?w=600" alt=""   /></a></p>
<p>Das Gleiche versuchen wir jetzt mal mit einem AjaxFehler. Nehmen wir beispielsweise den HTTP-Errorcode 503 (Gateway bzw. Server antwortet nicht).<br />
Darauf müssen wir in einer Applikation normalerweise reagieren.<br />
Das zu simulieren ist natürlich nicht ganz so trivial wie der Succes-Fall, aber weit weniger kompliziert, wie erwartet.</p>
<p>Beispielsweise könnten wir in der onEvent-Methode des AjaxBehaviors einfach einen HTTP-Fehlercode zurückgeben.</p>
<p><pre class="brush: java;">
@Overrides
protected void onEvent(AjaxRequestTarget target) {
throw new AbortWithHttpErrorCodeException(503, &quot;I need to check that&quot;);
]
</pre></p>
<p><a href="http://splitshade.files.wordpress.com/2011/09/http_failure.png"><img class="aligncenter size-full wp-image-673" title="http_failure" src="http://splitshade.files.wordpress.com/2011/09/http_failure.png?w=600" alt=""   /></a></p>
<p>Mit einer normalen Exception funktion das übrigens nicht, denn das ist kein HTTP-Fehler und wird Serverseitig behandelt und zeigt normalerweise eine ErrorPage oder ähnliches an.</p>
<p>Den letzten Parameter finde ich besonders interessant.</p>
<p><pre class="brush: java;">
channel :function() {return Wicket.$('ajaxLink1') != null;}.bind(this));
</pre></p>
<p>Was sind jetzt AjaxChannels?</p>
<p>Stellen wir uns das Szenario vor, wir haben eine Wicket-Applikation die sehr viel mit Ajax arbeitet.<br />
Stellen wir uns weiterhin vor, diese Applikation hat viele sogenannte Akkordeon-Module (das sind Module die via Javascript auf- bzw. zugeklappt<br />
werden können). Das Auf und zuklappen ist jeweils ein eigener Ajax-Call gegen das Backend, weil ja ggf. BackendServices getriggert werden müssen, um<br />
die Daten in den aufgeklappten Panels anzuzeigen. Ein einfaches Beispiel hierzu wäre die Anzeige von Adressdaten, die mit Hilfe einer Customer-ID vom Backend geladen werden müssen.<br />
Da die Daten erst geladen werden müssen kann es passieren, dass ein ProgressIndicator etwas länger angezeigt wird.<br />
Ungeduldige Kunden fangen dann an, und klicken wild auf der Applikation hin und her, öffnen und Schließen Panels und triggern so natürlich unbewusst BackendCalls, die die Applikation noch langsamer machen als sie sowieso schon ist.</p>
<p>Denn keine Ajax-Request gehem im Default-Modus verloren, jeder Backend-Call wird abgearbeitet, auch wenn das vielleicht gar nicht mehr notwendig wäre(<br />
im schlimmsten Fall klickt der Kunde für jedes Akkordion den Aufklappen-Button, der Backend-Call wird abgesetzt, die Daten geladen und das Akkordion blitzt nur kurz auf, weil der Kunde schon 3 Akkordeons weiter ist, das Laden der Daten war also völlig umsonst.)s</p>
<h2>Ajax Channels</h2>
<p>Wicket arbeitet per Default im synchronen Ajax-Modus, d.h. alle Ajax-Requests werden gequeued.<br />
Wie das gemacht wird sieht man am besten wieder, wenn man wieder einen Blick in die Datei wicket-ajax.js wirft.</p>
<p>Hier hab ich für euch die relevanten Sourcen kopiert.</p>
<p><pre class="brush: jscript;">
/**
* Channel management
*
* Wicket Ajax requests are organized in channels. A channel maintain the order of
* requests and determines, what should happen when a request is fired while another
* one is being processed. The default behavior (stack) puts the all subsequent requests
* in a queue, while the drop behavior limits queue size to one, so only the most
* recent of subsequent requests is executed.
* The name of channel determines the policy. E.g. channel with name foochannel|s is
* a stack channel, while barchannel|d is a drop channel.
*
* The Channel class is supposed to be used through the ChannelManager.
*/
Wicket.Channel = Wicket.Class.create();
Wicket.Channel.prototype = {
initialize: function(name) {
var res = name.match(/^([^|]+)\|(d|s)$/)
if (res == null)
this.type ='s'; // default to stack
else
this.type = res[2];
this.callbacks = new Array();
this.busy = false;
},

schedule: function(callback) {
if (this.busy == false) {
this.busy = true;
try {
return callback();
} catch (exception) {
this.busy = false;
Wicket.Log.error(&quot;An error occurred while executing Ajax request:&quot; + exception);
}
} else {
Wicket.Log.info(&quot;Channel busy - postponing...&quot;);
if (this.type == 's') // stack
this.callbacks.push(callback);
else /* drop */
this.callbacks[0] = callback;
return null;
}
},

done: function() {
var c = null;

if (this.callbacks.length &gt; 0) {
c = this.callbacks.shift();
}

if (c != null &amp;&amp; typeof(c) != &quot;undefined&quot;) {
Wicket.Log.info(&quot;Calling postponed function...&quot;);
// we can't call the callback from this call-stack
// therefore we set it on timer event
window.setTimeout(c, 1);
} else {
this.busy = false;
}
}
};

/**
* Channel manager maintains a map of channels.
*/
Wicket.ChannelManager = Wicket.Class.create();
Wicket.ChannelManager.prototype = {
initialize: function() {
this.channels = new Array();
},

// Schedules the callback to channel with given name.
schedule: function(channel, callback) {
var c = this.channels[channel];
if (c == null) {
c = new Wicket.Channel(channel);
this.channels[channel] = c;
}
return c.schedule(callback);
},

// Tells the ChannelManager that the current callback in channel with given name
// has finished processing and another scheduled callback can be executed (if any).
done: function(channel) {
var c = this.channels[channel];
if (c != null)
c.done();
}
};

// Default channel manager instance
Wicket.channelManager = new Wicket.ChannelManager();
</pre></p>
<p>Interessant ist zunächst mal die Regular Expression im Initialize-Callback des Ajax-Channels.</p>
<p><pre class="brush: jscript;">
name.match(/^([^|]+)\|(d|s)$/)
</pre></p>
<p>Wie interpretiert man diese Regular Expression jetzt?</p>
<p>Falls euch langweilig ist versucht ihr selber das herauszufinden, für alle anderen gibts direkt hier die Lösung.<br />
Die Regular-Expression greift für alles, was folgendes Muster hat:</p>
<p><pre class="brush: xml;">
myAjaxChannel|s
myAjaxChannel|d
irgendEinString|s
irgendEinString|d
</pre></p>
<p>Was aber bedeuten diese Ausdrücke?</p>
<p>Hierzu muss man wissen, dass Wicket zwei Modi unterscheidet, wie Ajax-Requests verarbeitet werden.</p>
<p>Synchroner / Asynchroner Ajax Modus</p>
<p>Im synchronen (Queue- oder Stack-Modus) werden alle Ajax-Requests in einer oder mehreren Queues gepoolt.<br />
Die verschiedenen Modi werden durch sogenannte Channels abgebildet.<br />
Werfen wir hierzu nochmals einen genauen Blick auf die Implementierung eines Ajax-Channels und hier speziell die schedule-Routine.</p>
<p><pre class="brush: jscript;">
schedule: function(callback) {
if (this.busy == false) {
this.busy = true;
try {
return callback();
} catch (exception) {
this.busy = false;
Wicket.Log.error(&quot;An error occurred while executing Ajax request:&quot; + exception);
}
} else {
Wicket.Log.info(&quot;Channel busy - postponing...&quot;);
if (this.type == 's') // stack
this.callbacks.push(callback);
else /* drop */
this.callbacks[0] = callback;
return null;
}
}
</pre></p>
<p>Der erste Teil des if-Blocks ist erst mal uninteressant, denn jeder Ajax-Request wird sofort verarbeitet, wenn nicht gerade ein anderer AjaxRequest aktiv ist.<br />
Viel interessanter ist der else-Zweig.</p>
<p>Wenn der Channel-Type &#8216;s&#8217; ist (S steht für Stackable, es handelt sich also um einen Queue-Channel), wird der Ajax-Call in eine Liste gespeichert.<br />
Wenn es sich nicht um einen Stack-Channel handelt, dann wird das oberste Element in der Liste ersetzt (in diesem Fall kann sowieso nur ein Element in der Liste sein) und ist quasi der Top-Kandidat als nächster AjaxRequest.</p>
<p>Jetzt sollte auch langsam klar werden, was es mit den zuvor erwähnten, etwas kryptischen Regular-Expressions auf sich hat.</p>
<p>Channelnames haben entweder die Form</p>
<p><pre class="brush: plain;">
meinAjaxChannel|s
</pre></p>
<p>oder die Form</p>
<p><pre class="brush: plain;">
meinAjaxChannel|d
</pre></p>
<p>Über den Character hinter dem |-Symbol unterscheidet Wicket, welche Art Channel für einen bestimmten Ajax-Call verwendet wird.</p>
<p>Wenn wir jetzt das Beispiel von vorhin ein wenig weiterspinnen, wären die AjaxRequests zum Öffnen der Akkordion-Panels nicht Stackable- bzw. Queue-Channels, sondern Drop-Channels, dann würde die Wicket tatsächlich immer nur den letzten Akkordion öffnen und den entsprechenden BackendCall absetzen.<br />
Alle anderen Requests würden einfach verfallen und niemals zum Server geschickt werden.</p>
<p>Bevor wir noch tiefer einsteigen schauen wir und das Ganze am besten an einem Beispiel an.</p>
<p>Hierfür erzeugen wir uns zunächst mal in HomePage.html folgendes Schnipsel:</p>
<p><pre class="brush: xml;">

&lt;a href=&quot;#&quot;&gt;

&lt;/a&gt;

</pre></p>
<p>Dies ist zum Einen ein WicketContainer, der als Container für einen ListView dient, in diesem sollen 4 AjaxLinks gerendert werden, die ein Laufrad zeigen, sobald der Button betätigt wird.</p>
<p>In die onClick-Methode bauen wir einen TimeOut von sagen wir 5 Sekunden ein, um langlaufende Backend-Transaktionen zu simulieren.</p>
<p>Der Java-Code ist hier:</p>
<p><pre class="brush: java;">

List links = Arrays.asList(new String[] { &quot;Link1&quot;, &quot;Link2&quot;,
&quot;Link3&quot;, &quot;Link4&quot; });
ListView listView = new ListView(&quot;linkList&quot;, links) {

private static final long serialVersionUID = 1L;

@Override
protected void populateItem(ListItem item) {
item.add(new IndicatingAjaxLink(&quot;indicatingAjaxLink&quot;) {

private static final long serialVersionUID = 1L;

@Override
public void onClick(AjaxRequestTarget target) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
target.appendJavaScript(&quot;alert('indicating link clicked')&quot;);
}

}.add(new Label(&quot;message&quot;, item.getModelObject())));
}
};

</pre></p>
<p>Um es uns möglichst einfach zu machen verwenden wir keine einfachen <strong>AjaxLinks</strong> sondern <strong>IndicatingAjaxLinks</strong>, da diese schon genau das Verhalten simulieren, das wir jetzt brauchen.<br />
Die IndicatingAjaxLinks blenden ein Laufrad ein, sobald sie geklickt werden. Das ist einfach über ein Behavior gelöst.<br />
Öffnet man jetzt die Seite und klickt alle Links an, ergibt sich folgendes Bild.</p>
<p><a href="http://splitshade.files.wordpress.com/2011/09/ajaxlinks1.png"><img class="aligncenter size-full wp-image-678" title="ajaxLinks" src="http://splitshade.files.wordpress.com/2011/09/ajaxlinks1.png?w=600" alt=""   /></a><br />
Jeder Link hat einen Timeout von 5 Sekunden in der <em>onClick</em>-Methode definiert.<br />
Hier sieht man sehr schön die serielle Abarbeitung von AjaxRequests.<br />
Es sieht zwar so aus, als wären alle Requests bereits abgeschickt, in Wirklichkeit aber<br />
ist nur der erste Request zum Server geschickt, hier wird der onClick-Handler aufgerufen und<br />
der Thread pausiert.</p>
<p>Die Ajax-Indikatoren sind per Javascript eingeblendet.<br />
Sind die ersten 5 Sekunden vorbei, startet der zweite Request, das dauert wieder 5 Sekunden.<br />
Es dauert also insgesamt 20 Sekunden, bis alle Ajax-Requests abgehandelt sind, da immer nur<br />
einer zum Server geschickt wird, der Rest landet in der AjaxChannel-Queue des ChannelManagers.</p>
<p>Betrachten wir kurz noch das generierte Javascript der AjaxLinks.</p>
<p><pre class="brush: jscript;">
if (function(){return Wicket.$('indicatingAjaxLink8') != null;}.bind(this)()) { Wicket.showIncrementally('indicatingAjaxLink8--ajax-indicator');}var wcall=wicketAjaxGet('wicket/page?1-2.IBehaviorListener.1-linkList-1-indicatingAjaxLink',function() { ;Wicket.hideIncrementally('indicatingAjaxLink8--ajax-indicator');}.bind(this),function() { ;Wicket.hideIncrementally('indicatingAjaxLink8--ajax-indicator');}.bind(this), function() {return Wicket.$('indicatingAjaxLink8') != null;}.bind(this));return !wcall;
</pre></p>
<p>Das meiste sollte uns bekannt vorkommen.<br />
Was auffällt, man sieht hier nichts von Channels. Per Default wird kein Channel generiert und<br />
alle Wicket-Ajax-Funktionalität läuft im Default-Channel,also bereits beim Client<br />
serialisiert.</p>
<p>Jetzt betrachten wir, die die Situation verbessert werden kann.<br />
Denn klickt der User auf alle 4 Links kann (muss aber nicht) es besser sein, nur den jeweils<br />
letzten Request zu verarbeiten.</p>
<p>Um das zu simulieren überschreiben wir einfach das onClick-Ajaxbehavior des Links. Hierzu muss man wissen, jede Komponente kann nur jeweils einen Event-Handler für ein bestimmtes Event haben.</p>
<p><pre class="brush: jscript;">

item.add(new IndicatingAjaxLink(&quot;indicatingAjaxLink&quot;) {

private static final long serialVersionUID = 1L;

protected AjaxEventBehavior newAjaxEventBehavior(String event) {
return new AjaxEventBehavior(&quot;onclick&quot;){

@Override
protected void onEvent(AjaxRequestTarget target) {
onClick(target);
}

protected String getChannelName() {
return &quot;ajaxChannel|d&quot;;
};

};
};

</pre></p>
<p>Für uns von Interesse ist hier die Methode <strong>getChannelName()</strong> des AbstractDefaultAjaxBehaviors.</p>
<p>Diese Methode liefert genau eines der zuvor bereits definierten Pattern (<strong>channelName|s</strong> oder <strong>channelName|d</strong> oder <strong>null</strong>was einem |s Channel entspricht).</p>
<p>Da wir einen Drop-Channel verwenden möchten, verwenden wir den ChannelName &#8222;<strong>ajaxChannel|d</strong>&#8222;.</p>
<p>Betrachten wir sofort wieder das generierte Javascript.</p>
<p><pre class="brush: jscript;">

if (function(){return Wicket.$('indicatingAjaxLink6') != null;}.bind(this)()) { Wicket.showIncrementally('indicatingAjaxLink6--ajax-indicator');}var wcall=wicketAjaxGet('wicket/page?0-1.IBehaviorListener.1-linkList-3-indicatingAjaxLink',function() { ;Wicket.hideIncrementally('indicatingAjaxLink6--ajax-indicator');}.bind(this),function() { ;Wicket.hideIncrementally('indicatingAjaxLink6--ajax-indicator');}.bind(this), function() {return Wicket.$('indicatingAjaxLink6') != null;}.bind(this), 'ajaxChannel|d');

</pre></p>
<p>Ganz am Ende im Skript sieht man, dass der richtige Ajax-Channel generiert wurde.</p>
<p>Wie aber verhält sich die Applikation?</p>
<p><a href="http://splitshade.files.wordpress.com/2011/09/screenshot-2.png"><img class="aligncenter size-full wp-image-681" title="Screenshot-2" src="http://splitshade.files.wordpress.com/2011/09/screenshot-2.png?w=600" alt=""   /></a>Scheinbar etwas unerwartet, aber nur bis man etwas genauer darüber nachdenkt.</p>
<p>Das Laufrad bei Link1 verschwindet nach 5 Sekunden. Das Laufrad bei Link4 nach weiteren 5 Sekunden. Die Laufräder bei Link2 + Link3 verschwinden überhaupt nicht.</p>
<p>Das macht Sinn.</p>
<ol>
<li>Beim Klick auf Link1 wird der Request abgeschickt und verarbeitet.</li>
<li>Der Klick auf Link2 setzt einen neuen Request in die Queue.</li>
<li>Der Klick auf Link3 überschreibt den Request von Link2.</li>
<li>Der Klick auf Link4 überschreibt den Request von Link3.</li>
<li>Ist der Link1-Request verarbeitet, wird sofort der Link4-Request verarbeitet. Die Request von Link2 und Link3 sind verschwunden.</li>
</ol>
<p>Das Ausblenden des Laufrads wird aber im Success- bzw. im Fehlerfall ausgeblendet, nicht jedoch wenn der Request gar nicht erst verarbeitet wird. Ein sehr schönes Beispiel.</p>
<p>Übrigens, mit Wicket 1.5.1 wird das Ganze noch schöner, ich habe mich sehr daran gestört, dass man hier mit Strings arbeiten muss. Deshalb hab ich für die AjaxChannels eine kleine Convenience-API bereit gestellt die ab Wicket 1.5.1 verfügbar sein wird. Wer sich das Ganze jetzt schon anschauen möchte, <a href="http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/ajax/AjaxChannel.java?view=markup&amp;pathrev=1166210">hier</a> ein kleiner Vorgeschmack.</p>
<h3>AjaxRequestTarget</h3>
<p>Was wir jetzt schon einige Male verwendet haben, worauf ich aber noch nicht genauer eingegagen bin ist das <strong>AjaxRequestTarget</strong>.</p>
<p>Diesen Code kennen wir schon:</p>
<p><pre class="brush: plain;">

add(new AjaxLink(&quot;ajaxLink&quot;) {
@Override
public void onClick(&lt;strong&gt;AjaxRequestTarget&lt;/strong&gt; target) {
target.appendJavaScript(&quot;alert('hello world!');&quot;);
}
});

</pre></p>
<p>Quasi in jeder Ajax-Methode bekommen wir vom Framework freundlicherweise den Schlüssel zur Wicket-Ajax-Engine übergeben, und zwar das <strong>AjaxRequestTarget</strong>.</p>
<p>Was kann ich mit dem AjaxRequestTarget machen?</p>
<ol>
<li>Javascript direkt zum Client schicken und zwar nach dem AjaxCall</li>
<li>Javascript direkt zum Client schicken und zwar vor dem Call</li>
<li>Bestimmte Komponenten neu zeichnen bzw. updaten.</li>
</ol>
<p>Um Javascript direkt zum Client zu schicken bietet das AjaxRequestTarget die Methoden <strong>appendJavascript(String script)</strong> bzw.<strong> prependJavascript(String script).</strong></p>
<p>Die Funktionsweise ist sprechend, deswegen gehe ich hier nicht näher darauf ein.</p>
<p>Um Komponenten neu zu zeichnen wird die <strong>add(Component component)</strong>-Methode verwendet. Wicket bietet mit dieser Methode die Möglichkeit, Komponenten in die RenderQeueu zu legen, die dann auf der Clientseite upgedatet werden.</p>
<p>Wichtig! Alle Komponenten die upgedatet werden sollen müssen eine Markup-ID rendern, das geht entweder, indem der Komponente bereits im Html eine id vergeben wird.</p>
<p><pre class="brush: xml;">
</pre></p>
<p>oder Codeseitig, indem folgendes aufgerufen wird.</p>
<p><pre class="brush: plain;">

Label label = new Label(&quot;text&quot;,&quot;Anzeigetext&quot;)
label.setOutputMarkupId(true);

</pre></p>
<h2>AjaxLazyLoadPanel</h2>
<p>Es gibt die Möglichkeit, Komponenten &#8222;Lazy&#8220; zu laden. D.h. beim Laden der Komponente wird ein Laufrad eingeblendet, und erst wenn die Komponente fertig geladen ist, wird die Komponente eingeblendet.</p>
<p>Das kann zum Einen verwendet werden, um lang ladenden Komponenten Zeit zu geben, sich fertig zu rendern, oder aber auch um auf Fehler zu reagieren, die bei eventuellen Backend-Calls auftreten können.</p>
<p>Betrachten wir das Ganze ein wenig genauer.<br />
Die Klasse, die uns diese wunderbare Funktionalität bietet ist das <strong>AjaxLazyLoadPanel</strong>.</p>
<p>Um das <strong>AjaxLazyLoadPanel</strong> verwenden zu können müssen wir uns die Wicket-Extensions besorgen.<br />
Der Maven-Archetype war so freundlich, und diese gleich mit zu generieren, wir müssen sie nur einkommentieren, falls noch nicht geschehen:</p>
<p><pre class="brush: xml;">

    org.apache.wicket
    wicket-extensions
    ${wicket.version}

</pre></p>
<p>für den gradle-build einfach folgende Zeile in die Dependencies mit aufnehmen:</p>
<p><pre class="brush: java;">
compile  &quot;org.apache.wicket:wicket-extensions:$wicketVersion&quot;
</pre></p>
<p>Der relevante Codeteil im LazyLoadPanel ist hier zu sehen:</p>
<p><pre class="brush: java;">
protected void respond(final AjaxRequestTarget target)
			{
				if (state &lt; 2)
				{
					Component component =   getLazyLoadComponent( LAZY_LOAD_COMPONENT_ID);
					AjaxLazyLoadPanel.this.replace(component);
					setState((byte)2);
				}
				target.add(AjaxLazyLoadPanel.this);

			}
</pre></p>
<p>Am besten wird sein, wir betrachten das LazyLoadPanel einfach mal in Aktion:</p>
<p><a href="http://splitshade.files.wordpress.com/2011/09/lazyloading.png"><img class="size-full wp-image-693 aligncenter" title="lazyloading" src="http://splitshade.files.wordpress.com/2011/09/lazyloading.png?w=600" alt=""   /></a><br />
<a href="http://splitshade.files.wordpress.com/2011/09/lazy2.png"><img class="size-full wp-image-694 aligncenter" title="lazy2" src="http://splitshade.files.wordpress.com/2011/09/lazy2.png?w=600" alt=""   /></a></p>
<p>Hier der Code dazu:</p>
<p><pre class="brush: plain;">
&lt;div wicket:id=&quot;lazyLoading&quot;/&gt;
</pre></p>
<p>und den Javacode dazu:</p>
<p><pre class="brush: java;">
protected AjaxLazyLoadPanel lazyLoadingPanel(){
		return new AjaxLazyLoadPanel(&quot;lazyLoading&quot;) {

			@Override
			public Component getLazyLoadComponent(String markupId) {
				try {
					Thread.sleep(10000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				return new Label(markupId, &quot;Lazy Loading works!&quot;);
			}
		};
	}
</pre></p>
<p>Das LazyLoadPanel rendert zunächst den ProgressIndicator, und ändert diesen in die richtige Komponente die von <strong>getLazyLoadComponent</strong> aufgerufen wird.<br />
Das schöne ist, hier können wir sogar noch ExceptionHandling einbauen.</p>
<p>Das Problem ist, normalerweise treten Exceptions nicht im Konstruktor der Komponente auf, sondern beim Rendern.<br />
Beispielsweise treten die meisten Exceptions beim Zugriff auf BackendSysteme auf. Der Zugriff auf diese Systeme erfolgt meistens über <strong>LoadableDetachableModels</strong>, und zum Zeitpunkt der Exception kann man leider meistens nicht mehr angemessen darauf reagieren.</p>
<p>Das sieht anders aus bei der Verwendung von AjaxLazyLoadPanels, wir simulieren einfach mal eine Komponente, die mit einem Model arbeitet, dass zur Laufzeit eine Exception wirft, also eine echte Real-Life-Problematik.</p>
<p>Folgendes Model verwenden wir hierzu:</p>
<p><pre class="brush: java;">
public class ExceptinThrowingModel extends LoadableDetachableModel{

	@Override
	protected Object load() {

		throw new RuntimeException(&quot;Error loading Component&quot;);
	}

}
</pre></p>
<p>Und bauen uns das Label im LazyLoadPanel folgendermaßen auf:</p>
<p><pre class="brush: java;">
return new Label(markupId, new ExceptinThrowingModel());
</pre></p>
<p>Das Ganze resultiert wie zu erwarten hierin:</p>
<p><a href="http://splitshade.files.wordpress.com/2011/09/exception.png"><img class="size-full wp-image-698 aligncenter" title="exception" src="http://splitshade.files.wordpress.com/2011/09/exception.png?w=600" alt=""   /></a></p>
<p>Das schöne ist aber, dass wir jetzt die Möglichkeit haben, angemessen darauf zu reagieren, und zwar so:</p>
<p><pre class="brush: java;">
try {
					IModel model = new ExceptinThrowingModel();
					//check the Backend Call
					model.getObject();
					return new Label(markupId, model);
				} catch (Exception e) {
					return new Label(markupId, &quot;Es ist ein Fehler aufgetreten!&quot;);
				}
</pre></p>
<p>Der Code selber gefällt mir nicht besonders, gerade weil wir hier das model.getObject() extra aufrufen müssen um auf eventuelle Fehler zu reagieren, das verursacht natürlich unnötigen Traffic, aber mir ist momentan keine Möglichkeit bekannt, das besser zu machen.</p>
<p>Für Tipps bin ich sehr dankbar.<a href="http://splitshade.files.wordpress.com/2011/09/error.png"><img class="size-full wp-image-699 aligncenter" title="error" src="http://splitshade.files.wordpress.com/2011/09/error.png?w=600" alt=""   /></a></p>
<h2>Wicket &amp; JQuery</h2>
<p>Wicket bringt schon eine sehr mächtige Ajax-Engine mit, mit der man alle &#8222;normalen&#8220; Ajax-Probleme und Anforderungen umsetzen kann. Geht es aber darum, der Oberfläche noch den letzten Schliff zu verpassen, dann wirds ein wenig komplizierter. Spätestens hier lohnt es sich, sich ein ausgewachsenes Ajax-Framework mal genauer anzuschauen.</p>
<p>Mein Tipp hier: <a href="http://jquery.org/">JQuery</a> &#8211; eine unglaublich einfach zu verwendendes, aber gleichzeitig unglaublich mächtiges Ajax-Framework.</p>
<p>Dies hier ist kein Artikel über JQuery, nichtsdesto trotz betrachten wir kurz, was mit JQuery alles möglich ist.</p>
<p>Hierzu laden wir uns zunächst mal die <a href="http://code.jquery.com/jquery-1.6.4.min.js">JQuery-Library</a>, einfacherweise ist dies nur ein Javascript-File und binden die vorerst mal direkt in unsere Html-Seite ein. Hierzu laden wir das File herunter und legen es in das lokale Filesystem, und zwar im webapp-Ordner.</p>
<p><a href="http://splitshade.files.wordpress.com/2011/09/bild.png"><img class="aligncenter size-full wp-image-723" title="bild" src="http://splitshade.files.wordpress.com/2011/09/bild.png?w=600" alt=""   /></a></p>
<p><pre class="brush: plain;">
&lt;script type=&quot;text/javascript&quot; src=&quot;jquery-1.6.4.min.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
$(document).ready(function(){
alert(&quot;Jquery is in place!&quot;);
})
&lt;/script&gt;

</pre></p>
<p>Zunächst binden wir die JQuery-API ein.<br />
Anschließend arbeiten wir mit folgendem Skript:</p>
<p><pre class="brush: plain;">
$(document).ready(function(){})
</pre></p>
<p>Über <strong>$(document)</strong> sprechen wir das aktuelle Dokument an. Über <strong>ready()</strong> haben wir eine Möglichkeit, einen Callback zu hinterlegen, der dann ausgeführt wird, wenn der DOM vollständig geladen wurde.</p>
<p>In diesem Fall geben wir zunächst einfach einen <strong>alert()</strong> aus, um zu prüfen, ob die JQuery-Anbindung funktioniert.</p>
<p><a href="http://splitshade.files.wordpress.com/2011/09/bild2.png"><img class="aligncenter size-full wp-image-725" title="bild2" src="http://splitshade.files.wordpress.com/2011/09/bild2.png?w=600" alt=""   /></a>JQuery ist also zunächst bereit.</p>
<p>Schauen wir uns also mal an, was man damit alles so machen kann.</p>
<p>Die mächtigste Funktion von JQuery sind mit Sicherheit die Selektoren, es gibt unzählige Möglichkeiten, Elemente aus dem DOM zu selektieren. Beispielsweise so:</p>
<p><pre class="brush: plain;">

$(document).ready(function(){
$('.headline').click(function(){
alert('on click handler in place')
})
})

</pre></p>
<p>Wichtig ist, das Script im onReady-Handler der Seite aufzurufen, da nur hier alle Elemente bereit sind.</p>
<p>Mit dem Selektor <strong>$(&#8216;.headline&#8217;)</strong> werden alle Elemente ausgewählt, die eine bestimmte CSS-Klasse haben, in diesem Beispiel alle Elemente mit der Klasse headLine.</p>
<p>Um dies zu testen geben wir der Headline die soweiso schon da ist die Klasse, nun ja, &#8216;headLine&#8217;.</p>
<p><pre class="brush: plain;">

&lt;h1 class=&quot;headline&quot; wicket:id=&quot;hello&quot;&gt;&lt;/h1&gt;

</pre></p>
<p>Laden wir die Seite nun neu, ist der onClick-Handler installiert.</p>
<p><a href="http://splitshade.files.wordpress.com/2011/09/bild3.png"><img class="aligncenter size-full wp-image-726" title="bild3" src="http://splitshade.files.wordpress.com/2011/09/bild3.png?w=600" alt=""   /></a>Nun ist ein alert nicht gerade Magie, was aber zum Beispiel auch geht ist folgendes:</p>
<p><pre class="brush: plain;">

$(document).ready(function(){
$('.headline').click(function(){
$(this).fadeOut();
})
})

</pre></p>
<p>Dies blendet die Überschrift langsam aus, bis sie verschwunden ist. Über <strong>$(this)</strong> kann das Element referenziert werden, auf dem der Handler installiert wurde.</p>
<p>Ok, das Schöne an JQuery ist, dass es sehr schnell zu erlernen ist. Idealerweise baut ihr zunächst mal direkt auf dem Beispiel auf und experimentiert ein bisschen.</p>
<h3>Integration mit Wicket</h3>
<p>Was wir bisher gemacht haben hätte auch wunderbar ohne Wicket funktioniert, wir hätten auch direkt JQuery in eine leere Html-Seite einbauen können. Was uns hier aber primär interessiert ist ja die Möglichkeit, JQuery mit Wicket zusammen zu verwenden. Zunächst mal sollten wir analysieren, wie wir JQuery in die Wicket Applikation einbinden. Mit Wicket 1.5 ist das sehr einfach über ein Behavior realisierbar.</p>
<p><pre class="brush: java;">

public class JQueryBehavior extends Behavior {

private static final long serialVersionUID = 1L;

public static final String JQUERY = &quot;jquery-1.6.4.min.js&quot;;

@Override
public void renderHead(Component component, IHeaderResponse response) {
super.renderHead(component, response);
response.renderJavaScriptReference(new PackageResourceReference(JQueryBehavior.class, JQUERY ));
}
}}

</pre></p>
<p>Über die Klasse IHeaderResponse hat man die Möglichkeit, CSS- oder Javascript-Referenzen im &lt;Head&gt; zu rendern.<br />
Das Schöne an Behaviors ist, dass sie auch dafür sorgen, dass Referenzen nur einmal gerendert werden und nicht mehrmals.</p>
<p>Damit das Ganze funktioniert kopieren wir die JQuery-Datei in das Package, wo auch die Klasse liegt.</p>
<p>Das Behavior kann jetzt überall in der Applikation verwendet werden.<br />
Wir werden das Behavior direkt in der Page verwenden, und zwar so:</p>
<p><pre class="brush: java;">
public HomePage(final PageParameters parameters) {
add(new JQueryBehavior());
...
}
</pre></p>
<p>Was Wicket uns hier rausrendert ist das:</p>
<p><pre class="brush: plain;">
&lt;script type=&quot;text/javascript&quot; src=&quot;&lt;a href=&quot;view-source:http://localhost:8080/wicket/resource/de.md.jquery.JQueryBehavior/jquery-1.6.4.min-ver-1316715616000.js&quot;&gt;wicket/resource/de.md.jquery.JQueryBehavior/jquery-1.6.4.min-ver-1316715616000.js&lt;/a&gt;&quot;&gt;&lt;/script&gt;
</pre></p>
<p>Die Skripte funktionieren weiter wie bisher, wenn wir sie vom HEAD in den Body verschieben.<br />
Im Head ist die Reihenfolge noch wichtig, in der die Skripte importiert werden und die können wir leider nicht kontrollieren.</p>
<p>Hier nochmal zur Sicherheit das komplette Html dazu:</p>
<p><pre class="brush: plain;">
&lt;!DOCTYPE html&gt;
&lt;html xmlns:wicket=&quot;http://wicket.apache.org&quot;&gt;
&lt;head&gt;
&lt;meta charset=&quot;utf-8&quot; /&gt;
&lt;title&gt;Apache Wicket Quickstart&lt;/title&gt;
&lt;link
href='http://fonts.googleapis.com/css?family=Yanone+Kaffeesatz:regular,bold'
rel='stylesheet' type='text/css' /&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;style.css&quot; type=&quot;text/css&quot; media=&quot;screen&quot;
title=&quot;Stylesheet&quot; /&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
$(document).ready(function(){
$('.headline').click(function(){
$(this).fadeOut();
})
})
&lt;/script&gt;
&lt;h1 wicket:id=&quot;hello&quot;&gt;&lt;/h1&gt;
&lt;a href=&quot;#&quot; wicket:id=&quot;ajaxLink&quot;&gt;Click me&lt;/a&gt;
&lt;div wicket:id=&quot;ajaxText&quot; /&gt;

&lt;wicket:container wicket:id=&quot;linkList&quot;&gt;
&lt;a href=&quot;#&quot; wicket:id=&quot;indicatingAjaxLink&quot;&gt;
&lt;span wicket:id=&quot;message&quot; /&gt;
&lt;/a&gt;
&lt;/wicket:container&gt;

&lt;div wicket:id=&quot;lazyLoading&quot;/&gt;

&lt;div style=&quot;width:500px; height:100px; background: gray;&quot;&gt;
&lt;form wicket:id=&quot;form&quot;&gt;
Anrede: &lt;div wicket:id=&quot;salutation&quot;/&gt;
Vorname: &lt;div wicket:id=&quot;firstName&quot;/&gt;&lt;br/&gt;
&lt;input type=&quot;submit&quot;/&gt;
&lt;/form&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;

</pre></p>
<p>Das ist zunächst mal alles was notwendig ist, um JQuery einzubinden. Normalerweise ist es so, dass man in einer Applikation eine abstrakte Page bereitstellt.<br />
Dies ist der perfekte Ort, um dieses Behavior einzubinden.</p>
<p>Zunächst mal legen wir einen neuen Style direkt im &lt;head&gt; an:</p>
<p><pre class="brush: plain;">
&lt;style type=&quot;text/css&quot;&gt;
.blackBeauty{display:none;position:absolute; right: 0px; top: 0px;width:150px; height:150px; background:black;color: red}
&lt;/style&gt;
</pre></p>
<p>Dieser Style rendert eine Schwarze Box mit roter Schrift im rechten oberen Eck der Seite.<br />
Das Element ist initial unsichtbar.</p>
<p>Jetzt wollen wir einen Link rendern, der dieses Element einblendet und zwar mit ein wenig Dynamik, wozu haben wir<br />
schließlich JQuery, oder? Gleichzeitig blendet das Skript den Link aus, so dass er nur einmalig geklickt werden kann.<br />
Ich weiß, dies ist ein sehr einfacher Use-Case, zeigt aber wie JQuery sehr einfach verwendet werden kann, der Rest ist<br />
reine Spielerei.</p>
<p>Zunächst legen wir uns ein kleines Skript-File an (fadein.js):</p>
<p><pre class="brush: jscript;">
$(&quot;.blackBeauty&quot;).fadeIn(&quot;slow&quot;);
$(&quot;#${id}&quot;).fadeOut(&quot;slow&quot;);
</pre></p>
<p>Dazu schreiben wir uns wieder ein Behavior:</p>
<p><pre class="brush: java;">

public class FadeInBehavior extends AjaxEventBehavior {

public FadeInBehavior(String event) {
super(event);
}

@Override
protected IAjaxCallDecorator getAjaxCallDecorator() {
return new AjaxCallDecorator() {
@Override
public CharSequence decorateScript(Component c, CharSequence script) {
PackageTextTemplate template = new PackageTextTemplate(FadeInBehavior.class, &quot;fadein.js&quot;);
Map&lt;String, Object&gt; map = new HashMap&lt;String, Object&gt;();
map.put(&quot;id&quot;, getComponent().getMarkupId());
return template.interpolate(map).asString();
}
};
}

@Override
protected void onEvent(AjaxRequestTarget target) {
//never called
}
}

</pre></p>
<p>Wir benutzen hierfür eine AjaxEventBehavior, von dem wir ableiten. Dieses Behavior rendert uns automatisch einen onClick-Handler, der normalerweise<br />
das Serverseitige Behavior aufruft, das möchten wir hier aber nicht, sondern wir möchten ein Clientseitiges JQuery-Skript aufrufen.</p>
<p>Hierfür überschreiben wir die Methode getAjaxCallDecorator &#8211; Mit einem AjaxCallDecorator hat man die Möglichkeit, das gerenderte Ajaxskript<br />
zu dekorieren.<br />
Wir benutzen den Decorator nicht, um das Skript zu dekorieren, sondern wir überschreiben es einfach.</p>
<p>Mit folgendem Code-Fragment laden wir das externe Javascript-File und interpolieren die Platzhalter:</p>
<p><pre class="brush: java;">
PackageTextTemplate template = new PackageTextTemplate(FadeInBehavior.class, &quot;fadein.js&quot;);
Map&lt;String, Object&gt; map = new HashMap&lt;String, Object&gt;();
map.put(&quot;id&quot;, getComponent().getMarkupId());
return template.interpolate(map).asString();
</pre></p>
<p>Der Platzhalter ${id} wird ersetzt durch die Markup-ID des Links und fertig.</p>
<p>So, dies war ein relativ langer Artikel, ich hoffe ich konnte einigermaßen klar machen, wie schön und einfach Ajax<br />
mit Wicket funktioniert.<br />
Ich freue mich über Kommentare , Anregungen etc.</p>
<p>Den Sourcecode könnt ihr euch von <a href="dilgerma/Wicket-Ajax-on-splitshade.wordpress.com.git">Github</a> ziehen.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/splitshade.wordpress.com/648/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/splitshade.wordpress.com/648/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/splitshade.wordpress.com/648/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/splitshade.wordpress.com/648/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/splitshade.wordpress.com/648/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/splitshade.wordpress.com/648/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/splitshade.wordpress.com/648/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/splitshade.wordpress.com/648/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/splitshade.wordpress.com/648/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/splitshade.wordpress.com/648/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/splitshade.wordpress.com/648/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/splitshade.wordpress.com/648/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/splitshade.wordpress.com/648/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/splitshade.wordpress.com/648/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=splitshade.wordpress.com&amp;blog=5189437&amp;post=648&amp;subd=splitshade&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://splitshade.wordpress.com/2011/09/22/ajax-mit-wicket-wie-funktionierts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0f446b406cac4629cd7ddf73607054b5?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">splitshade</media:title>
		</media:content>

		<media:content url="http://svn.apache.org/repos/asf/wicket/sandbox/dashorst/animation/logo-top.png" medium="image">
			<media:title type="html">wicket</media:title>
		</media:content>

		<media:content url="http://splitshade.files.wordpress.com/2011/09/successful_ajax_call.png" medium="image">
			<media:title type="html">successful_ajax_call</media:title>
		</media:content>

		<media:content url="http://splitshade.files.wordpress.com/2011/09/http_failure.png" medium="image">
			<media:title type="html">http_failure</media:title>
		</media:content>

		<media:content url="http://splitshade.files.wordpress.com/2011/09/ajaxlinks1.png" medium="image">
			<media:title type="html">ajaxLinks</media:title>
		</media:content>

		<media:content url="http://splitshade.files.wordpress.com/2011/09/screenshot-2.png" medium="image">
			<media:title type="html">Screenshot-2</media:title>
		</media:content>

		<media:content url="http://splitshade.files.wordpress.com/2011/09/lazyloading.png" medium="image">
			<media:title type="html">lazyloading</media:title>
		</media:content>

		<media:content url="http://splitshade.files.wordpress.com/2011/09/lazy2.png" medium="image">
			<media:title type="html">lazy2</media:title>
		</media:content>

		<media:content url="http://splitshade.files.wordpress.com/2011/09/exception.png" medium="image">
			<media:title type="html">exception</media:title>
		</media:content>

		<media:content url="http://splitshade.files.wordpress.com/2011/09/error.png" medium="image">
			<media:title type="html">error</media:title>
		</media:content>

		<media:content url="http://splitshade.files.wordpress.com/2011/09/bild.png" medium="image">
			<media:title type="html">bild</media:title>
		</media:content>

		<media:content url="http://splitshade.files.wordpress.com/2011/09/bild2.png" medium="image">
			<media:title type="html">bild2</media:title>
		</media:content>

		<media:content url="http://splitshade.files.wordpress.com/2011/09/bild3.png" medium="image">
			<media:title type="html">bild3</media:title>
		</media:content>
	</item>
		<item>
		<title>Die neue Postbank Online Banking Seite ist mit Wicket gemacht.</title>
		<link>http://splitshade.wordpress.com/2011/09/12/die-neue-postbank-online-banking-seite-ist-mit-wicket-gemacht/</link>
		<comments>http://splitshade.wordpress.com/2011/09/12/die-neue-postbank-online-banking-seite-ist-mit-wicket-gemacht/#comments</comments>
		<pubDate>Mon, 12 Sep 2011 06:13:25 +0000</pubDate>
		<dc:creator>splitshade</dc:creator>
				<category><![CDATA[Wicket]]></category>

		<guid isPermaLink="false">http://splitshade.wordpress.com/?p=719</guid>
		<description><![CDATA[Wicket ist auf dem Vormarsch. Die neue Postbank Seite ist komplett in Wicket gemacht. Sehr schick, funktional und performant. Gefällt mir sehr gut!<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=splitshade.wordpress.com&amp;blog=5189437&amp;post=719&amp;subd=splitshade&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><img class="alignright" title="wicket" src="http://svn.apache.org/repos/asf/wicket/sandbox/dashorst/animation/logo-top.png" alt="" width="238" height="237" /></p>
<p><strong>Wicket</strong> ist auf dem Vormarsch.</p>
<p>Die neue Postbank Seite ist komplett in Wicket gemacht.</p>
<p>Sehr schick, funktional und performant. Gefällt mir sehr gut!</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/splitshade.wordpress.com/719/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/splitshade.wordpress.com/719/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/splitshade.wordpress.com/719/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/splitshade.wordpress.com/719/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/splitshade.wordpress.com/719/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/splitshade.wordpress.com/719/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/splitshade.wordpress.com/719/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/splitshade.wordpress.com/719/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/splitshade.wordpress.com/719/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/splitshade.wordpress.com/719/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/splitshade.wordpress.com/719/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/splitshade.wordpress.com/719/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/splitshade.wordpress.com/719/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/splitshade.wordpress.com/719/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=splitshade.wordpress.com&amp;blog=5189437&amp;post=719&amp;subd=splitshade&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://splitshade.wordpress.com/2011/09/12/die-neue-postbank-online-banking-seite-ist-mit-wicket-gemacht/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0f446b406cac4629cd7ddf73607054b5?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">splitshade</media:title>
		</media:content>

		<media:content url="http://svn.apache.org/repos/asf/wicket/sandbox/dashorst/animation/logo-top.png" medium="image">
			<media:title type="html">wicket</media:title>
		</media:content>
	</item>
		<item>
		<title>Wicket 1.5 ist draussen</title>
		<link>http://splitshade.wordpress.com/2011/09/08/wicket-1-5-ist-draussen/</link>
		<comments>http://splitshade.wordpress.com/2011/09/08/wicket-1-5-ist-draussen/#comments</comments>
		<pubDate>Thu, 08 Sep 2011 19:28:08 +0000</pubDate>
		<dc:creator>splitshade</dc:creator>
				<category><![CDATA[Wicket]]></category>

		<guid isPermaLink="false">http://splitshade.wordpress.com/?p=642</guid>
		<description><![CDATA[Ein Guter Tag! Holt es euch hier. Ich habe einen  (zugegeben kleinen Teil) dazu beigetragen. https://issues.apache.org/jira/browse/WICKET-3634 https://issues.apache.org/jira/browse/WICKET-3652 https://issues.apache.org/jira/browse/WICKET-4023 https://issues.apache.org/jira/browse/WICKET-4024 Viel Spaß mit dem neuen Release!<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=splitshade.wordpress.com&amp;blog=5189437&amp;post=642&amp;subd=splitshade&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><img class="aligncenter" title="wicket" src="http://t1.gstatic.com/images?q=tbn:ANd9GcQUkqdaU46vfyje2dS8EOxU85xohE5E7kCX1un6OYb1mmd9Gi8H" alt="" width="190" height="189" /></p>
<p>Ein Guter Tag!</p>
<p>Holt es euch <a href="http://wicket.apache.org/2011/09/07/wicket-1.5-released.html">hier</a>.</p>
<p>Ich habe einen  (zugegeben kleinen Teil) dazu beigetragen.</p>
<p><a href="https://issues.apache.org/jira/browse/WICKET-3634">https://issues.apache.org/jira/browse/WICKET-3634</a></p>
<p><a href="https://issues.apache.org/jira/browse/WICKET-3652">https://issues.apache.org/jira/browse/WICKET-3652</a></p>
<p><a href="https://issues.apache.org/jira/browse/WICKET-4023">https://issues.apache.org/jira/browse/WICKET-4023</a></p>
<p><a href="https://issues.apache.org/jira/browse/WICKET-4024">https://issues.apache.org/jira/browse/WICKET-4024</a></p>
<p>Viel Spaß mit dem neuen Release!</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/splitshade.wordpress.com/642/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/splitshade.wordpress.com/642/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/splitshade.wordpress.com/642/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/splitshade.wordpress.com/642/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/splitshade.wordpress.com/642/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/splitshade.wordpress.com/642/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/splitshade.wordpress.com/642/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/splitshade.wordpress.com/642/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/splitshade.wordpress.com/642/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/splitshade.wordpress.com/642/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/splitshade.wordpress.com/642/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/splitshade.wordpress.com/642/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/splitshade.wordpress.com/642/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/splitshade.wordpress.com/642/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=splitshade.wordpress.com&amp;blog=5189437&amp;post=642&amp;subd=splitshade&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://splitshade.wordpress.com/2011/09/08/wicket-1-5-ist-draussen/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/0f446b406cac4629cd7ddf73607054b5?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">splitshade</media:title>
		</media:content>

		<media:content url="http://t1.gstatic.com/images?q=tbn:ANd9GcQUkqdaU46vfyje2dS8EOxU85xohE5E7kCX1un6OYb1mmd9Gi8H" medium="image">
			<media:title type="html">wicket</media:title>
		</media:content>
	</item>
	</channel>
</rss>
