<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Molindo Techblog &#187; Michael Sparer</title>
	<atom:link href="http://techblog.molindo.at/author/msp/feed" rel="self" type="application/rss+xml" />
	<link>http://techblog.molindo.at</link>
	<description>Molindo Techblog – formerly known as talk-on-tech.blogspot.com</description>
	<lastBuildDate>Tue, 20 Dec 2011 10:22:19 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Compass: Role based searching using CompassQueryFilter</title>
		<link>http://techblog.molindo.at/2009/12/compass-role-based-searching-using-compassqueryfilter.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=compass-role-based-searching-using-compassqueryfilter</link>
		<comments>http://techblog.molindo.at/2009/12/compass-role-based-searching-using-compassqueryfilter.html#comments</comments>
		<pubDate>Fri, 18 Dec 2009 15:14:37 +0000</pubDate>
		<dc:creator>Michael Sparer</dc:creator>
				<category><![CDATA[Compass]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://techblog.molindo.at/?p=157</guid>
		<description><![CDATA[While implementing a forum with wicket, spring, hibernate and compass for search, I recently ran into a problem: there are topics and posts that should only visible for some users. Say there&#8217;s a moderator forum where all content should only be visible for &#8230; well moderators . We&#8217;re using role based authentication in our apps,  [...]]]></description>
			<content:encoded><![CDATA[<p>While implementing <a href="http://www.setlist.fm/forum">a forum</a> with wicket, spring, hibernate and compass for search, I recently ran into a problem: there are topics and posts that should only visible for some users. Say there&#8217;s a moderator forum where all content should only be visible for &#8230; well moderators <img src='http://techblog.molindo.at/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> .<br />
<span id="more-157"></span><br />
We&#8217;re using role based authentication in our apps,  where each User object has one role that can in turn imply other roles. I&#8217;m leaving out some method, but you can imagine the IRole interface like that:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">interface</span> IRole <span style="color: #009900;">&#123;</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">List</span> getImpliedRoles<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">boolean</span> hasRole<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">final</span> IRole role<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>we&#8217;re using an implementation that&#8217;s quite close to this:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">enum</span> SessionRole <span style="color: #000000; font-weight: bold;">implements</span> IRole <span style="color: #009900;">&#123;</span>
&nbsp;
ANONYMOUS<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>,
USER<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>,
MODERATOR<span style="color: #009900;">&#40;</span>USER<span style="color: #009900;">&#41;</span>,
ADMIN<span style="color: #009900;">&#40;</span>MODERATOR<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">List</span> _impliedRoles<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">private</span> SessionRole<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
   _impliedRoles <span style="color: #339933;">=</span> <span style="color: #003399;">Collections</span>.<span style="color: #006633;">emptyList</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">private</span> SessionRole<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">final</span> IRole... <span style="color: #006633;">impliedRoles</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    _name <span style="color: #339933;">=</span> createName<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
   <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">HashSet</span> set <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">HashSet</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
   <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">final</span> IRole impliedRole <span style="color: #339933;">:</span> impliedRoles<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
   set.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span>impliedRole<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
   set.<span style="color: #006633;">addAll</span><span style="color: #009900;">&#40;</span>impliedRole.<span style="color: #006633;">getImpliedRoles</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
_impliedRoles <span style="color: #339933;">=</span> <span style="color: #003399;">Collections</span>.<span style="color: #006633;">unmodifiableList</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">ArrayList</span><span style="color: #009900;">&#40;</span>set<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">List</span> getImpliedRoles<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
<span style="color: #000000; font-weight: bold;">return</span> _impliedRoles<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">boolean</span> hasRole<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">final</span> IRole role<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
<span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000000; font-weight: bold;">this</span> <span style="color: #339933;">==</span> role <span style="color: #339933;">||</span> _impliedRoles.<span style="color: #006633;">contains</span><span style="color: #009900;">&#40;</span>role<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>And for the sake of completeness, here the indexed entity (only showing the relevant fields):</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> ForumEntry <span style="color: #009900;">&#123;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">String</span> _headline<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">String</span> _text<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">private</span> IRole _readRole<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>The visibility of the forum wasn&#8217;t a problem at all &#8211; where it got complicated was when performing a search. Of course the lucene index contains all posts and thus the search runs over all entries and also returns all entries &#8211; leading to results showing up for regular users that should be for moderators&#8217; eyes only.</p>
<p>The first ideas that came to my mind (and also the first I abandoned) were:</p>
<ol>
<li>Performing a regular search without considering any roles at all, then sort out the ones the user isn&#8217;t allowed to see</li>
<li>Save all roles that are allowed to see the entry to the ForumEntry</li>
<li>Add a hook into the indexing process and save the moderator entries in an other index (probably the worst idea)</li>
</ol>
<p>1. is quite bad as far as design is concerned and not really handy when it comes to paging through the results, 2. would bloat the index a bit and each IRole would not only have to know its implied roles, but also its inferring roles (the roles that are higher in hierarchy). E.g. USER would have to know that MODERATOR and ADMIN have at least the same rights. This might seem easy for this case but gets complicated with a more complex role structure. 3. no that&#8217;s really bad &#8230; we want to use the same index (and also the same UI) for all searches.</p>
<p>The solution is pretty simple to implement but was <a href="http://forum.compass-project.org/message.jspa?messageID=160476">very hard to find</a>: CompassQueryFilters. As the name suggests, a CompassQueryFilter is</p>
<blockquote><p>A filter used to filter out query results.</p></blockquote>
<p>For filtering my ForumEntry entities based on the user role, I use a boolean query builder and add a should-rule for each implied role and for the role itself. A should role for a boolean query applies when <strong>at least one of the rules applies to the matching hits</strong>. The code goes something like that:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">CompassSession session <span style="color: #339933;">=</span> ...<span style="color: #339933;">;</span>
IRole userRole <span style="color: #339933;">=</span> ...<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">final</span> CompassQueryBuilder build <span style="color: #339933;">=</span> session.<span style="color: #006633;">queryBuilder</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">final</span> CompassQueryStringBuilder queryStringBuilder <span style="color: #339933;">=</span> build.<span style="color: #006633;">queryString</span><span style="color: #009900;">&#40;</span>qry<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">final</span> CompassQuery q <span style="color: #339933;">=</span> queryStringBuilder.<span style="color: #006633;">toQuery</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">final</span> CompassQueryFilterBuilder queryFilterBuilder <span style="color: #339933;">=</span> session.<span style="color: #006633;">queryFilterBuilder</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">final</span> CompassQueryBuilder.<span style="color: #006633;">CompassBooleanQueryBuilder</span> booleanQueryBuilder <span style="color: #339933;">=</span> build.<span style="color: #006633;">bool</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>userRole.<span style="color: #006633;">getImpliedRoles</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
<span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">final</span> IRole r <span style="color: #339933;">:</span> userRole.<span style="color: #006633;">getImpliedRoles</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
booleanQueryBuilder.<span style="color: #006633;">addShould</span><span style="color: #009900;">&#40;</span>build.<span style="color: #006633;">term</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;readRole&quot;</span>, r.<span style="color: #006633;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">toLowerCase</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
booleanQueryBuilder.<span style="color: #006633;">addShould</span><span style="color: #009900;">&#40;</span>build.<span style="color: #006633;">term</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;readRole&quot;</span>, userRole.<span style="color: #006633;">toString</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">toLowerCase</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">final</span> CompassQueryFilter queryFilter <span style="color: #339933;">=</span> filterBuilder.<span style="color: #006633;">query</span><span style="color: #009900;">&#40;</span>booleanQueryBuilder.<span style="color: #006633;">toQuery</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
q.<span style="color: #006633;">setFilter</span><span style="color: #009900;">&#40;</span>queryFilter<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>One last caveat: the indexed IRole field of ForumEntry cannot be empty or null, the whole filtering process would then yield wrong results. A simple solution is to add a base role to the existing roles which every role implies, something like that:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">enum</span> SessionRole <span style="color: #000000; font-weight: bold;">implements</span> IRole <span style="color: #009900;">&#123;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">DEFAULT</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>,
ANONYMOUS<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">DEFAULT</span><span style="color: #009900;">&#41;</span>,
USER<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">DEFAULT</span><span style="color: #009900;">&#41;</span>,
MODERATOR<span style="color: #009900;">&#40;</span>USER<span style="color: #009900;">&#41;</span>,
ADMIN<span style="color: #009900;">&#40;</span>MODERATOR<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://techblog.molindo.at/2009/12/compass-role-based-searching-using-compassqueryfilter.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Wicket: A Neat Url Encoding Strategy and some basic SEO</title>
		<link>http://techblog.molindo.at/2008/12/wicket-a-neat-url-encoding-strategy-and-some-basic-seo.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=wicket-a-neat-url-encoding-strategy-and-some-basic-seo</link>
		<comments>http://techblog.molindo.at/2008/12/wicket-a-neat-url-encoding-strategy-and-some-basic-seo.html#comments</comments>
		<pubDate>Tue, 09 Dec 2008 09:03:00 +0000</pubDate>
		<dc:creator>Michael Sparer</dc:creator>
				<category><![CDATA[SEO]]></category>
		<category><![CDATA[Wicket]]></category>

		<guid isPermaLink="false">http://tech.molindo.at/2008/12/wicket-a-neat-url-encoding-strategy-and-some-basic-seo.html</guid>
		<description><![CDATA[After a year of working extensively with Apache Wicket I want to share some stuff I&#8217;ve been using over and over again and might be useful for you as well. In this first post it&#8217;s a custom URL Encoding Strategy and some related basic SEO. Pages often depend on entities &#8211; e.g. a Customer or [...]]]></description>
			<content:encoded><![CDATA[<p>After a year of working extensively with <a href="http://wicket.apache.org">Apache Wicket</a> I want to share some stuff I&#8217;ve been using over and over again and might be useful for you as well. In this first post it&#8217;s a custom URL Encoding Strategy and some related basic SEO.</p>
<p>Pages often depend on entities &#8211; e.g. a Customer or a product and as those pages should be bookmarkable as well, there has to be a unique way to tell the page which entity to use. As entities either don&#8217;t have unique names or one wants to avoid having an (database) index over the name column, the index-ID is for most applications the way to go. As it&#8217;s usually undesireable to expose the database ID of an entity in the URL, it has to be encoded and decoded somehow to get from myshop.com/customer/12 to myshop.com/customer/ea34cff &#8230; or something like that.<br />
<span id="more-31"></span><br />
Using a custom Url-mounting strategy makes it a breeze:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">abstract</span> <span style="color: #000000; font-weight: bold;">class</span> IndexedIdEncryptingUrlCodingStrategy <span style="color: #000000; font-weight: bold;">extends</span> LowercaseOnlyIndexedUrlEncodingStrategy <span style="color: #009900;">&#123;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000066; font-weight: bold;">int</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> _encryptedParams<span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// serverroot is e.g. http://www.mypage.com - required for 301 redirects in baseclass</span>
<span style="color: #000000; font-weight: bold;">public</span> IndexedIdEncryptingUrlCodingStrategy<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> mountPath, <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> serverRoot, <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000000; font-weight: bold;">Class</span> bookmarkablePageClass, <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000066; font-weight: bold;">int</span>... <span style="color: #006633;">encryptedParmas</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
<span style="color: #000000; font-weight: bold;">super</span><span style="color: #009900;">&#40;</span>mountPath, serverRoot, bookmarkablePageClass<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
_encryptedParams <span style="color: #339933;">=</span> encryptedParmas<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">public</span> IndexedIdEncryptingUrlCodingStrategy<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> mountPath, <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> serverRoot, <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000000; font-weight: bold;">Class</span> bookmarkablePageClass, <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> pageMapName, <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000066; font-weight: bold;">int</span>... <span style="color: #006633;">encryptedParmas</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
<span style="color: #000000; font-weight: bold;">super</span><span style="color: #009900;">&#40;</span>mountPath, serverRoot, bookmarkablePageClass<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
_encryptedParams <span style="color: #339933;">=</span> encryptedParmas<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
@SuppressWarnings<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;unchecked&quot;</span><span style="color: #009900;">&#41;</span>
@Override
<span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000066; font-weight: bold;">void</span> appendParameters<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">final</span> AppendingStringBuffer url, <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">Map</span> params<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
<span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000066; font-weight: bold;">int</span> index <span style="color: #339933;">:</span> _encryptedParams<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
<span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> indexStr <span style="color: #339933;">=</span> <span style="color: #003399;">Integer</span>.<span style="color: #006633;">toString</span><span style="color: #009900;">&#40;</span>index<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">Object</span> val <span style="color: #339933;">=</span> params.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span>indexStr<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>val <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span> <span style="color: #339933;">&amp;</span>amp<span style="color: #339933;">;&amp;</span>amp<span style="color: #339933;">;</span> val <span style="color: #000000; font-weight: bold;">instanceof</span> <span style="color: #003399;">Integer</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
params.<span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span>indexStr, encodeId<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #003399;">Integer</span><span style="color: #009900;">&#41;</span> val<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000000; font-weight: bold;">super</span>.<span style="color: #006633;">appendParameters</span><span style="color: #009900;">&#40;</span>url, params<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
@Override
<span style="color: #000000; font-weight: bold;">protected</span> ValueMap onDecodeParameters<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> urlFragment, <span style="color: #000000; font-weight: bold;">final</span> ValueMap urlParameters<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">final</span> <span style="color: #000066; font-weight: bold;">int</span> index <span style="color: #339933;">:</span> _encryptedParams<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
<span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> indexStr <span style="color: #339933;">=</span> <span style="color: #003399;">Integer</span>.<span style="color: #006633;">toString</span><span style="color: #009900;">&#40;</span>index<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">Object</span> val <span style="color: #339933;">=</span> urlParameters.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span>indexStr<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>val <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span> <span style="color: #339933;">&amp;</span>amp<span style="color: #339933;">;&amp;</span>amp<span style="color: #339933;">;</span> val <span style="color: #000000; font-weight: bold;">instanceof</span> <span style="color: #003399;">String</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
urlParameters.<span style="color: #006633;">put</span><span style="color: #009900;">&#40;</span>indexStr, decodeId<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span><span style="color: #009900;">&#41;</span> val<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">return</span> urlParameters<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000066; font-weight: bold;">int</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> getEncryptedParams<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
<span style="color: #000000; font-weight: bold;">return</span> _encryptedParams<span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">abstract</span> <span style="color: #003399;">String</span> encodeId<span style="color: #009900;">&#40;</span><span style="color: #003399;">Integer</span> val<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">abstract</span> <span style="color: #003399;">Integer</span> decodeId<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span> val<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>This class&#8217;s baseclass is used for SEO only: it just checks if there are only lowercase letters in the URL and does a 301 redirect to the lowercase variant of the page if not.<br />
Why lowercase only: The first of the Ten SEO Commandments (if there was such a thing) is: &#8220;<span style="font-weight:bold">Thou shalt only have one URL per page</span>&#8221; &#8211; and for bots <span style="font-style:italic">http://www.myshop.com/customer/Foobar</span> and <span style="font-style:italic">http://www.myshop.com/customer/fOoBar</span> are two different URLs &#8211; which is a bad thing as far as duplicate content is concerned. Well, it could also be uppercase only or camelcase only &#8211; but lowercase makes it easier to read for humans and is also easier to implement than camelcase.</p>
<p>Then just mount the page like that:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">mount<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> IndexedIdEncryptingUrlCodingStrategy<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;/customer&quot;</span>, <span style="color: #0000ff;">&quot;http://www.mypage.com&quot;</span>, HomePage.<span style="color: #000000; font-weight: bold;">class</span>, <span style="color: #0000ff;">&quot;id&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>and construct the page params like that:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">final</span> PageParameters params <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> PageParameters<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
params.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;id&quot;</span>, myEntity.<span style="color: #006633;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// add e.g. a link</span>
add<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> BookmarkablePageLink<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;link&quot;</span>, HomePage.<span style="color: #000000; font-weight: bold;">class</span>, params<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Download the files:<br />
<a href="http://molindo.at/files/msp/IndexedIdEncryptingUrlCodingStrategy.java">IndexedIdEncryptingUrlCodingStrategy.java</a><br />
<a href="http://molindo.at/files/msp/LowercaseOnlyIndexedUrlEncodingStrategy.java">LowercaseOnlyIndexedUrlEncodingStrategy.java</a></p>
<p>In my next post I&#8217;ll get a bit more into Wicket &amp; SEO: Show a more SEO way to encode URLs, how to deal with the JSESSIONID and how to apply the code shown today on a Page. Stay tuned &#8211; and consider subscribing</p>
<p>PS: If &#8220;thou convet my code&#8221;: the code is public domain, feel free to do whatever you like to do with it. If you have any suggestions or implement enhancements, just post them in the comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://techblog.molindo.at/2008/12/wicket-a-neat-url-encoding-strategy-and-some-basic-seo.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Fun Friday Second Life</title>
		<link>http://techblog.molindo.at/2008/07/fun-friday-second-life.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=fun-friday-second-life</link>
		<comments>http://techblog.molindo.at/2008/07/fun-friday-second-life.html#comments</comments>
		<pubDate>Fri, 25 Jul 2008 08:26:00 +0000</pubDate>
		<dc:creator>Michael Sparer</dc:creator>
				<category><![CDATA[Fun]]></category>

		<guid isPermaLink="false">http://tech.molindo.at/2008/07/fun-friday-second-life.html</guid>
		<description><![CDATA[I found a link to some interesting college art work while browsing SEOMoz&#8217;s roundup thursday. College students could gain an additional point in an exam if they could &#8216;answer&#8217; the following question: Choose a particular piece of web-related software, such as a particular web browser, operating system or text editor. Then draw a picture of [...]]]></description>
			<content:encoded><![CDATA[<p>I found a link to <a href="http://www.cs.washington.edu/education/courses/190m/08sp/exams/final/student_art.pdf">some interesting college art work </a>while browsing <a href="http://www.seomoz.org/blog/roundup-thursday-for-the-week-of-72008">SEOMoz&#8217;s roundup</a> thursday.<br />
College students could gain an additional point in an exam if they could &#8216;answer&#8217; the following question:</p>
<p><em>Choose a particular piece of web-related software, such as a particular web browser, operating system or text editor. Then draw a picture of what a typical user of that software looks like. </em></p>
<p><a href="http://www.songtexte.com/user/fuzy">Stefan </a>was sure he could have answered the exam question better than the rest &#8230; and for sure he did. but have a look for yourself.<br />
<span id="more-21"></span><br />
<a href="http://bp0.blogger.com/_uXeW0-_1vE0/SImO3QOUv6I/AAAAAAAAAAM/lgE_aRgJZ38/s1600-h/2ndlife_small.jpg"><img style="margin: 0px auto 10px;text-align: center;cursor: pointer;width: 358px;height: 421px" src="http://bp0.blogger.com/_uXeW0-_1vE0/SImO3QOUv6I/AAAAAAAAAAM/lgE_aRgJZ38/s320/2ndlife_small.jpg" border="0" alt="" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://techblog.molindo.at/2008/07/fun-friday-second-life.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Custom reuseable LoadableDetachableModel for Spring/Hibernate</title>
		<link>http://techblog.molindo.at/2008/05/a-custom-reuseable-loadabledetachablemodel-for-springhibernate.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=a-custom-reuseable-loadabledetachablemodel-for-springhibernate</link>
		<comments>http://techblog.molindo.at/2008/05/a-custom-reuseable-loadabledetachablemodel-for-springhibernate.html#comments</comments>
		<pubDate>Wed, 21 May 2008 16:28:00 +0000</pubDate>
		<dc:creator>Michael Sparer</dc:creator>
				<category><![CDATA[Hibernate]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[Wicket]]></category>

		<guid isPermaLink="false">http://tech.molindo.at/2008/05/a-custom-reuseable-loadabledetachablemodel-for-springhibernate.html</guid>
		<description><![CDATA[the annoyance org.hibernate.LazyInitializationException - could not initialize proxy - the owning Session was closedorg.hibernate.LazyInitializationException: could not initialize proxy - the owning Session was closed the problem Generally, detached objects in Hibernate are a bad thing when it comes to reusing objects between web-requests. Detached objects are objects that have been persistent but are not attached [...]]]></description>
			<content:encoded><![CDATA[<h2>the annoyance</h2>
<p><code><br />org.hibernate.LazyInitializationException - could not initialize proxy - the owning Session was closed<br />org.hibernate.LazyInitializationException: could not initialize proxy - the owning Session was closed<br /></code><br />
<h2>the problem</h2>
<p>Generally, detached objects in Hibernate are a bad thing when it comes to reusing objects between web-requests. Detached objects are objects that have been persistent but are not attached to a Hibernate session. They&#8217;re easily produced but can be a mess if it comes to Lazy-Loading or updating them. Just consider the following case</p>
<p><code><br />Foo foo = _myDAO.getFoo(); // attached object</p>
<p>add(new Link("fooLink", new Model(foo)) {</p>
<p>&nbsp;&nbsp;protected void onClick() {<br />&nbsp;&nbsp;&nbsp;&nbsp;Foo foo = (Foo) getModelObject(); // now it's detached as this is called in the next request<br />&nbsp;&nbsp;&nbsp;&nbsp;Bar bar = foo.getBar(); // possible lazy-loading exception if bar gets loaded lazily  </p>
<p>&nbsp;&nbsp;}<br />}<br /></code></p>
<h2>the solution</h2>
<p>First be sure to use the OpenSessionInViewFilter sothat a new hibernate session is opened when the request gets attached and closed when it gets detached.</p>
<p>Then the solution of course is a to use a LoadableDetachableModel that gets a fresh instance from the persistence-layer on each request. Could look like that:</p>
<p><code><br />IModel fooModel = new LoadableDetachableModel() {</p>
<p>&nbsp;&nbsp;protected Object load() {<br />&nbsp;&nbsp;&nbsp;&nbsp;return _myDAO.getFoo();<br />&nbsp;&nbsp;}<br />}</p>
<p>add(new Link("fooLink", fooModel) {</p>
<p>&nbsp;&nbsp;protected void onClick() {<br />&nbsp;&nbsp;&nbsp;&nbsp;Foo foo = (Foo) getModelObject(); // attached as LDM has loaded a fresh instance<br />&nbsp;&nbsp;&nbsp;&nbsp;Bar bar = foo.getBar(); // no lazy loading exception as still attached  </p>
<p>&nbsp;&nbsp;}<br />}<br /></code></p>
<h2>the improvement</h2>
<p>
<p>LoadableDetachableModels are a nice thing but it&#8217;s quite a lot of work to inject your DAO (or service) and then create a new LDM for each of your objects in each and every one of your panels. so we came up with a more generic version of the LoadableDetachableModel. First, let your model-objects implement an Interface, say IPersistentObject with the single method</p>
<p><code><br />&nbsp;&nbsp;Serializable getId();<br /></code></p>
<p>As your object are likely to have a primary key named id it&#8217;ll be no problem anyway. Then create the following class:</p>
<p><code><br />public class PersistentObjectModel extends LoadableDetachableModel {</p>
<p>&nbsp;&nbsp;private static final long serialVersionUID = 1L;</p>
<p>&nbsp;&nbsp;private final Class _clazz;</p>
<p>&nbsp;&nbsp;private final Serializable _id;</p>
<p>&nbsp;&nbsp;@SpringBean(name = "myDao")<br />&nbsp;&nbsp;private IMyDao _myDao;</p>
<p>&nbsp;&nbsp;@SuppressWarnings("unchecked")<br />&nbsp;&nbsp;public PersistentObjectModel(final T object) {<br />&nbsp;&nbsp;&nbsp;&nbsp;super(object);</p>
<p>           // object may be a hibernate proxy, so get the actual class<br />&nbsp;&nbsp;&nbsp;&nbsp;if (object instanceof HibernateProxy) {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_clazz = (Class) ((HibernateProxy) object).getHibernateLazyInitializer()<br />                                   .getImplementation().getClass();<br />&nbsp;&nbsp;&nbsp;&nbsp;} else {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_clazz = (Class) object.getClass();<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;_id = object.getId();<br />&nbsp;&nbsp;&nbsp;&nbsp;// inject the bean<br />&nbsp;&nbsp;&nbsp;&nbsp;InjectorHolder.getInjector().inject(this);<br />&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;public PersistentObjectModel(final Class clazz, final Serializable id) {<br />&nbsp;&nbsp;&nbsp;&nbsp;clazz = clazz;<br />&nbsp;&nbsp;&nbsp;&nbsp;_id = id;<br />&nbsp;&nbsp;&nbsp;&nbsp;// inject the bean<br />&nbsp;&nbsp;&nbsp;&nbsp;InjectorHolder.getInjector().inject(this);<br />&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;@Override<br />&nbsp;&nbsp;protected T load() {<br />&nbsp;&nbsp;&nbsp;&nbsp;// the DAO then simply passes the params to hibernate (or spring's hibernatetemplate<br />&nbsp;&nbsp;&nbsp;&nbsp;return _myDao.getById(_clazz, _id);<br />&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;@SuppressWarnings("unchecked")<br />&nbsp;&nbsp;@Override<br />&nbsp;&nbsp;public T getObject() {<br />&nbsp;&nbsp;&nbsp;&nbsp;return (T) super.getObject();<br />&nbsp;&nbsp;}</p>
<p>}<br /></code></p>
<p>This makes working with hibernate objects really easy. There are two options:</p>
<p></p>
<ol>
<li>Use the object e.g.
<p>setModel(new PersistentObjectModel(foo));</p>
<p></li>
<p>
<li>Use only class and id.
<p>This might happen e.g. if you pass your id using PageParameters (but better encrypt it <img src='http://techblog.molindo.at/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> )<br />setModel(new PersistentObjectModel(Foo.class, 1));</p>
<p></li>
<p></ol>
<p>
<p>Hope that saved you some time writing boilerplate code <img src='http://techblog.molindo.at/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' />  have fun</p>
]]></content:encoded>
			<wfw:commentRss>http://techblog.molindo.at/2008/05/a-custom-reuseable-loadabledetachablemodel-for-springhibernate.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Hibernate: could not read column value from result set?</title>
		<link>http://techblog.molindo.at/2008/05/hibernate-could-not-read-column-value-from-result-set.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=hibernate-could-not-read-column-value-from-result-set</link>
		<comments>http://techblog.molindo.at/2008/05/hibernate-could-not-read-column-value-from-result-set.html#comments</comments>
		<pubDate>Fri, 16 May 2008 13:26:00 +0000</pubDate>
		<dc:creator>Michael Sparer</dc:creator>
				<category><![CDATA[Hibernate]]></category>

		<guid isPermaLink="false">http://tech.molindo.at/2008/05/hibernate-could-not-read-column-value-from-result-set.html</guid>
		<description><![CDATA[I got this Error today after changing the primary key of my model objects from int to Serializable (as I wanted all of my objects, even the ones with a String primary key to use the same API, which was limited to int). But when I started the app I got the Error and the [...]]]></description>
			<content:encoded><![CDATA[<p>I got this Error today after changing the primary key of my model objects from int to Serializable (as I wanted all of my objects, even the ones with a String primary key to use the same API, which was limited to int). But when I started the app I got the Error and the following Exception:</p>
<blockquote><p>org.hibernate.type.SerializationException: could not deserialize<br />    at org.hibernate.util.SerializationHelper.deserialize(SerializationHelper.java:217)<br />    at org.hibernate.util.SerializationHelper.deserialize(SerializationHelper.java:240)<br />    at org.hibernate.type.SerializableType.fromBytes(SerializableType.java:82)<br />    at org.hibernate.type.SerializableType.get(SerializableType.java:39)<br />    at org.hibernate.type.NullableType.nullSafeGet(NullableType.java:163)<br />    at org.hibernate.type.NullableType.nullSafeGet(NullableType.java:154)<br />    &#8230;..</p></blockquote>
<p>I even got this one as cause:<br />
<blockquote>Caused by: java.io.EOFException<br />    at java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2279)<br />    at java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:2748)<br />    at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:780)<br />    at java.io.ObjectInputStream.(ObjectInputStream.java:280)<br />   &#8230;.</p></blockquote>
<p>EOF? wtf? Don&#8217;t get too confused with that EOF, the solution was simply to add the type of the id in the mapping file.</p>
<p>Before:</p>
<blockquote><p>&lt;id name=&#8221;id&#8221;&gt;<br />  &lt;generator class=&#8221;native&#8221;&gt;<br />&lt;/id&gt;</p></blockquote>
<p>After:<br />
<blockquote>&lt;id name=&#8221;id&#8221; <span style="font-weight: bold">type=&#8221;integer&#8221;</span>&gt; &lt;!&#8211; or long or string of whatever your <span style="font-weight: bold">hibernate </span>type is &#8211;&gt;<br />  &lt;generator class=&#8221;native&#8221;&gt;<br />&lt;/id&gt;</p></blockquote>
]]></content:encoded>
			<wfw:commentRss>http://techblog.molindo.at/2008/05/hibernate-could-not-read-column-value-from-result-set.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Wicket ChoiceRenderer for Enums</title>
		<link>http://techblog.molindo.at/2008/01/wicket-choicerenderer-for-enums.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=wicket-choicerenderer-for-enums</link>
		<comments>http://techblog.molindo.at/2008/01/wicket-choicerenderer-for-enums.html#comments</comments>
		<pubDate>Thu, 10 Jan 2008 17:25:00 +0000</pubDate>
		<dc:creator>Michael Sparer</dc:creator>
				<category><![CDATA[Wicket]]></category>

		<guid isPermaLink="false">http://tech.molindo.at/2008/01/wicket-choicerenderer-for-enums.html</guid>
		<description><![CDATA[I now got to the point where I wanted to put some i18n into my DropDownChoices. What I found out pretty soon was that you need an IChoiceRenderer to customise your DropDownChoices. If you don&#8217;t use one, you&#8217;ll get by default short values and toString display names. E.g. the enum enum { JOHN, PAUL, GEORGE, [...]]]></description>
			<content:encoded><![CDATA[<p>I now got to the point where I wanted to put some i18n into my DropDownChoices. What I found out pretty soon was that you need an IChoiceRenderer to customise your DropDownChoices. If you don&#8217;t use one, you&#8217;ll get by default short values and toString display names. E.g. the enum</p>
<p><code><br />enum { JOHN, PAUL, GEORGE, RINGO }<br /></code></p>
<p>produces an output like that</p>
<p><code><br />&lt;select name="beatles"&gt;<br />&lt;option value="0"&gt;JOHN&lt;/option&gt;<br />&lt;option value="1"&gt;PAUL&lt;/option&gt;<br />&lt;option value="2"&gt;GEORGE&lt;/option&gt;<br />&lt;option value="3"&gt;RINGO&lt;/option&gt;<br />&lt;/select&gt;<br /></code></p>
<p>But what I want is &#8220;John&#8221; instead of JOHN or &#8220;John Lennon, Rhythm Guitar&#8221; or anything but JOHN. On the mailinglist and in the wiki I discovered some complicated, overhead solutions using helper objects, so I decided to implement my own reusable enum-renderer that reads the display values from a properties file. All you have to do is to pass the Component that is responsible for the properties file.</p>
<p><code><br />public class EnumChoiceRenderer implements IChoiceRenderer {</p>
<p>private static final long serialVersionUID = 1L;</p>
<p>private final Component _resourceProvider;</p>
<p>public EnumChoiceRenderer(final Component resourceProvider) {<br /> _resourceProvider = resourceProvider;<br />}</p>
<p>public Object getDisplayValue(final Object object) {<br /> final Enum&lt;?&gt; v = (Enum&lt;?&gt;) object;<br /> return _resourceProvider.getString(v.name());<br />}</p>
<p>public String getIdValue(final Object object, final int index) {<br /> return Integer.toString(index);<br />}</p>
<p>}<br /></code></p>
<p>Yeah that was quite easy, but maybe saves some of you the burdon of using helper-classes <img src='http://techblog.molindo.at/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>Oh yes, the properties file looks something like that:<br /><code><br />JOHN=John Lennon, Rhythm Guitar<br />PAUL=Paul McCartney, Bass<br />GEORGE=George Harrison, Lead Guitar<br />RINGO=Ringo Starr, Drums<br /></code><br />what then produces the desired output:</p>
<p><code>&lt;select name="beatles"&gt;<br />&lt;option value="0"&gt;</code><code>John Lennon, Rhythm Guitar</code><code>&lt;/option&gt;<br />&lt;option value="1"&gt;</code><code>Paul McCartney, Bass</code><code>&lt;/option&gt;<br />&lt;option value="2"&gt;</code><code>George Harrison, Lead Guitar</code><code>&lt;/option&gt;<br />&lt;option value="3"&gt;</code><code>Ringo Starr, Drums</code><code>&lt;/option&gt;<br />&lt;/select&gt;</code></p>
]]></content:encoded>
			<wfw:commentRss>http://techblog.molindo.at/2008/01/wicket-choicerenderer-for-enums.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>svn: Base checksum mismatch</title>
		<link>http://techblog.molindo.at/2007/12/svn-base-checksum-mismatch.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=svn-base-checksum-mismatch</link>
		<comments>http://techblog.molindo.at/2007/12/svn-base-checksum-mismatch.html#comments</comments>
		<pubDate>Fri, 14 Dec 2007 13:27:00 +0000</pubDate>
		<dc:creator>Michael Sparer</dc:creator>
				<category><![CDATA[SVN]]></category>

		<guid isPermaLink="false">http://tech.molindo.at/2007/12/svn-base-checksum-mismatch.html</guid>
		<description><![CDATA[Today I had difficulties commiting a source file as I got this error svn: Checksum mismatch for /path/to/SourceFile.javaexpected: [checksum],actual: [checksum] The problem occurred after moving a package into a different source-folder, with the mentioned file as new file in it. If you&#8217;re experiencing the same problem, just stop trying to fix it &#8220;the nice way&#8221;. [...]]]></description>
			<content:encoded><![CDATA[<p>Today I had difficulties commiting a source file as I got this error
<pre>svn: Checksum mismatch for /path/to/SourceFile.javaexpected: [checksum],actual: [checksum]</pre>
<p>The problem occurred after moving a package into a different source-folder, with the mentioned file as new file in it. If you&#8217;re experiencing the same problem, just stop trying to fix it &#8220;the nice way&#8221;. Rather follow <a href="http://glob.bushi.net.nz/glob/2007/02/14/subversion-checksum-mismatch-easy-workaround/">this easy workaround</a> that suggests checking out the folder where the file lies into a temp-directory, then override your existing folder in your project with the newly checked out one.<br />It&#8217;s quick and dirty but it&#8217;s gonna save you a load of time <img src='http://techblog.molindo.at/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://techblog.molindo.at/2007/12/svn-base-checksum-mismatch.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>wicketstuff-push, bayeux and the memory leak</title>
		<link>http://techblog.molindo.at/2007/11/wicketstuff-push-bayeux-and-the-memory-leak.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=wicketstuff-push-bayeux-and-the-memory-leak</link>
		<comments>http://techblog.molindo.at/2007/11/wicketstuff-push-bayeux-and-the-memory-leak.html#comments</comments>
		<pubDate>Thu, 15 Nov 2007 08:46:00 +0000</pubDate>
		<dc:creator>Michael Sparer</dc:creator>
				<category><![CDATA[Comet]]></category>
		<category><![CDATA[Wicket]]></category>

		<guid isPermaLink="false">http://tech.molindo.at/2007/11/wicketstuff-push-bayeux-and-the-memory-leak.html</guid>
		<description><![CDATA[I&#8217;ve been fiddling around with reverse-ajax (or comet or pushlets) these days/weeks. You know, that stuff where the webserver keeps an open connection to the client and pushes new events to the client with just the transportation-delay &#8211; but no client interference. As described in my recent posts, I decided to use Apache Wicket for [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been fiddling around with reverse-ajax (or comet or pushlets) these days/weeks. You know, that stuff where the webserver keeps an open connection to the client and pushes new events to the client with just the transportation-delay &#8211; but no client interference. As described in my recent posts, I decided to use <a href="http://wicket.apache.org/">Apache Wicket</a> for my webapp, so I looked around if there&#8217;s something in the wicketstuff project that fits my needs. And yes, there is the <a href="http://sourceforge.net/projects/wicket-stuff/">wicketstuff-push</a> project that offers different implementations of server pushes. <a href="http://xhab.blogspot.com/">Xavier Hanin</a>, one of the men behind <a href="http://ant.apache.org/ivy/">Ivy</a>, and <a href="http://www.demay-fr.net/blog/">Vincent Demay</a> did great effort there to implement a timerbased PushImplementation and also a <a href="http://www.cometd.com/">Cometd-based</a> implementation of a event subscribe/publish mechanism. The latter uses an implementation of the <a href="http://svn.xantus.org/shortbus/trunk/bayeux/bayeux.html">Bayeux-spec</a> and the <a href="http://www.dojotoolkit.org/">Dojo-library</a> together with <a href="http://wicketstuff.org/confluence/display/STUFFWIKI/WicketStuff+Dojo">wicketstuff-dojo</a> to subscribe to channels and to process the pushes on client side.</p>
<p>Yesterday I took the time to have a closer look on how the Java implementation of the Bayeux protocol works and found out that each new client that subscribes to a channel gets stored in the Bayeux&#8217;s client-HashMap &#8230; and stays there. So apparently it is up to the user to remove the clients from there. Otherwise the HashMap would grow towards an OutOfMemoryError, which needed some 400.000 clients on my machine.<br />So how to get them out? Well it ain&#8217;t just that easy to say &#8220;on session unbinding I simply remove the client with the corresponding session id&#8221; as the client id the Bayeux protocol uses isn&#8217;t the http-session id. The client id also changes more frequently, a simple reload of the page is enough to have a new client id. So for my application, I subclassed CometdServlet (over which all request and thus all subscriptions are processed) and made a http-session &#8211; bayeux-client-session mapping. This means that I always know which session has which client id, and if the client-id differs, it simply gets removed from the Bayeux-map.</p>
<p>Problem solved</p>
<p>P.S.: Bayeux does the same with channels, so be careful with the amount of channels in your webapp<br />P.P.S.: Wicket&#8217;s first release candidate for version 1.3 is out *thumbs-up*</p>
]]></content:encoded>
			<wfw:commentRss>http://techblog.molindo.at/2007/11/wicketstuff-push-bayeux-and-the-memory-leak.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Some wicket impressions</title>
		<link>http://techblog.molindo.at/2007/08/some-wicket-impressions.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=some-wicket-impressions</link>
		<comments>http://techblog.molindo.at/2007/08/some-wicket-impressions.html#comments</comments>
		<pubDate>Wed, 29 Aug 2007 12:47:00 +0000</pubDate>
		<dc:creator>Michael Sparer</dc:creator>
				<category><![CDATA[Wicket]]></category>

		<guid isPermaLink="false">http://tech.molindo.at/2007/08/some-wicket-impressions.html</guid>
		<description><![CDATA[I already mentioned Apache Wicket in my first post and immediately received advice to not gloss &#8220;over a great framework too quickly&#8221;. This advice came from a guy named jonathan &#8230; coincidentally one of Wicket&#8217;s most ambitioned developers is Jonathan Locke, who&#8217;s always present in discussions about Wicket &#8230; so there may be a connection [...]]]></description>
			<content:encoded><![CDATA[<p>I already mentioned <a href="http://wicket.apache.org/">Apache Wicket</a> in my first post and immediately received advice to not gloss &#8220;over a great framework too quickly&#8221;. This advice came from a guy named jonathan &#8230; coincidentally one of Wicket&#8217;s most ambitioned developers is <a href="http://www.jroller.com/JonathanLocke/">Jonathan Locke</a>, who&#8217;s always present in discussions about Wicket &#8230; so there may be a connection to that guy who left a comment to my first post <img src='http://techblog.molindo.at/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> .</p>
<p>So I gave it a try. As the Wicket website <a href="http://wicket.apache.org/getting-wicket.html">suggests to use version</a><a href="http://wicket.apache.org/getting-wicket.html"> 1.3.0beta</a>, the first I did was to download it as maven dependency.<br /><code></p>
<p> &lt;groupId&gt;org.apache.wicket&lt;/groupId&gt;<br /> &lt;artifactId&gt;wicket&lt;/artifactId&gt;<br /> &lt;version&gt;${wicket.version}&lt;/version&gt;<br />&lt;/dependency&gt;</p>
<p>&lt;dependency&gt;<br /> &lt;groupId&gt;org.apache.wicket&lt;/groupId&gt;<br /> &lt;artifactId&gt;wicket-extensions&lt;/artifactId&gt;<br /> &lt;version&gt;${wicket.version}&lt;/version&gt;<br />&lt;/dependency&gt;<br /></code><br />Then I took a look around to find some code snippets or examples that could give me a smooth start. The <a href="http://wicket.apache.org/exampleguestbook.html">guestbook example</a> on the website was the first a had a look at (well after the hello world, which doesn&#8217;t count <img src='http://techblog.molindo.at/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> ). The guestbook was easy to understand and ran without problems &#8230;<br />Wicket&#8217;s AJAX support was the next thing I had a look at. I found some nice examples in the <a href="http://www.wicket-library.com/">Wicket Library</a> and on <a href="http://wicketstuff.org/">wicketstuff.org</a> (in fact the same on both websites). And yes, it was the guestbook with added ajax behaviour which I tried first. I adapted it a bit to my needs and tried to run it. It ended up by throwing a <span style="font-style: italic">MarkupNotFoundException </span>which suggested to<br /><code><br />Enable debug messages for org.apache.wicket.util.resource to get a list of all filenames tried<br /></code><br />as Guestbook.html could not be found. I enabled debug messages by adding the following line to my log4j.properties file.<br /><code><br />log4j.category.org.apache.wicket.util.resource=debug<br /></code><br />The debug message I got was<br /><code><br />[DEBUG] ResourceStreamLocator Attempting to locate resource 'org/example/wicket/Guestbook.html' on path [folders = [], webapppaths: []]<br /></code><br />I thought &#8220;uh, there aren&#8217;t any webapppaths or folders in wicket&#8217;s path, gotta add some&#8221;. I then entered the path in the web.xml file as property of the Wicket filter. Well, the path was then inside the brackets, but the exception still got thrown.<br />Eventually I saw the (my) mistake: there was a <span style="font-style: italic">&lt;wicket:extend&gt;</span> tag in the markup html, which was completely new to me. Having read the <a href="http://cwiki.apache.org/WICKET/markup-inheritance.html">wiki article about markup inheritance</a> and having removed the tag, the Guestbook ran without problems. Yepp it was my mistake to copy-paste the thing and to overlook the tag, but couldn&#8217;t the error message be a bit better/concise?</p>
<p><a href="http://herebebeasties.com/2007-08-17/wicket-bean-editor/">Alastair Maw&#8217;s BeanEditPanel</a> reminded me a lot of <a href="http://tapestry.apache.org/tapestry5/tapestry-core/guide/beaneditform.html">Tapestry&#8217;s BeanEditForm</a>, but of course doesn&#8217;t have all the BeanEditForm&#8217;s functionality (yet). But it was a great starting point for me to get a bit more into wicket &#8230; I already extended the BeanEditPanel a bit &#8230; yes, to be honest, the more I work with Wicket, the more I like it. The use of plain html and wicket IDs is a great concept and I also like the ease of adding AJAX behaviour. Just have a look at <a href="http://www.wicket-library.com/wicket-examples/ajax/">the ajax examples</a>.</p>
<p>A nice summary of wicket&#8217;s features can be found in <a href="http://ptrthomas.wordpress.com/2007/03/02/wicket-impressions-moving-from-spring-mvc-webflow/">Peter Thomas&#8217;s Blog</a>. I also recommend to read <a href="http://www.developer.com/java/web/article.php/3673576">Karthik Gurumurthy&#8217;s introduction</a>.</p>
<p>The only complaints I have so far are that I could not find the source code, which would be quite comfortable to have attached to the jar, as I sometimes like to see what&#8217;s going on behind the curtain&#8230; and no I don&#8217;t want to check it out from the SVN <img src='http://techblog.molindo.at/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> .<br />There&#8217;s also no link to the <a href="http://wicketstuff.org/wicket13doc/">1.3.0beta javadocs</a> on the official website. I found the link in a newsgroup post.</p>
<p>What I&#8217;m going to find out next is how the Validators work in Wicket. In a example I found, a Validator was added to a text field for instance like that<br /><code><br />TextField name = new TextField("name");<br />number.add(StringValidator.minimumLength(5));<br /></code><br />But contrary to the javadocs, a method FormComponent.add(IValidator) is not available &#8230; which I found a bit strange &#8230;</p>
<p>That&#8217;s all for now, and comments, especially to the validator stuff, are always welcome <img src='http://techblog.molindo.at/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://techblog.molindo.at/2007/08/some-wicket-impressions.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Creating custom components with Tapestry 5</title>
		<link>http://techblog.molindo.at/2007/08/creating-custom-components-with-tapestry-5.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=creating-custom-components-with-tapestry-5</link>
		<comments>http://techblog.molindo.at/2007/08/creating-custom-components-with-tapestry-5.html#comments</comments>
		<pubDate>Mon, 27 Aug 2007 15:08:00 +0000</pubDate>
		<dc:creator>Michael Sparer</dc:creator>
				<category><![CDATA[Tapestry]]></category>

		<guid isPermaLink="false">http://tech.molindo.at/2007/08/creating-custom-components-with-tapestry-5.html</guid>
		<description><![CDATA[As far as I&#8217;m concerned, I consider creating custom, reusable components as the supreme discipline of every web-framework. I remember fiddling about a custom tabbed panel in JSF some years ago &#8230; those were the days when it wasn&#8217;t easy to find JSF third-party components. I also remember that it took me ages to add [...]]]></description>
			<content:encoded><![CDATA[<p>As far as I&#8217;m concerned, I consider creating custom, reusable components as the supreme discipline of every web-framework. I remember fiddling about a custom tabbed panel in JSF some years ago &#8230; those were the days when it wasn&#8217;t easy to find JSF third-party components. I also remember that it took me ages to add some sort of AJAX behaviour, and I can&#8217;t really remember if I finally succeeded <img src='http://techblog.molindo.at/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' />  But times have changed, creating custom components is part of every almost every framework&#8217;s ref-docs and it is &#8230; or should be &#8230; easy to create them. Ideally just with combining already existing components to new ones.</p>
<p>As already mentioned in <a href="http://talk-on-tech.blogspot.com/2007/08/tapestryspring-integration.html">my previous post</a>, I&#8217;m playing around with <a href="http://tapestry.apache.org/tapestry5/">Tapestry 5</a> these days. So I decided to create my own component, a guestbook component. The guestbook should be as generic as possible, meaning that all kinds of Java beans should be valid entries. I.e. you should not be dependent on some fixed values such as name, e-mail and the message &#8230; well that really called for a <a href="http://tapestry.apache.org/tapestry5/tapestry-core/guide/beaneditform.html">BeanEditForm </a>to enter the values &#8230; and I thought about using some kind of <a href="http://tapestry.apache.org/tapestry5/tapestry-core/component-parameters.html#org.apache.tapestry.corelib.components.grid">Grid </a>to display the guestbook entries.</p>
<p>As a complete newbie in creating tapestry components, the first way to go was the <a href="http://wiki.apache.org/tapestry/Tapestry5HowTos">Tapestry wiki&#8217;s howto page for T5.</a> There, <a href="http://wiki.apache.org/tapestry/Tapestry5HowToCreateYourOwnComponents">Eric Vullings&#8217;s short introduction about creating custom components</a> merely gave me a quick overview over the rendering phases to override/implement when creating a component.<br />Then I took a cursory glance at the BeanEditForm&#8217;s and Grid&#8217;s source code to see how the components work and how they could be extended/used for my custom guestbook component. I quickly realised that it takes a bit more than a cursory glance to get the hang of the Grid (including the GridRows, GridColumns and GridPager components) but it needs less effort to figure out how the BeanEditForm works.</p>
<p>I decided to take the BeanEditForm straight away as part of my component and to adapt some of the Grid&#8217;s functionality to display the entries. I soon found myself copying most of the Grid&#8217;s code &#8230;. that was the right time to stop and to think about my approach once again. I was already down in adding my own <a href="http://tapestry.apache.org/tapestry5/tapestry-ioc/coerce.html">coercer </a>to the AppModule which was a lot of fun but nevertheless copying code can&#8217;t be the solution <img src='http://techblog.molindo.at/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> .<br />So I (ab)used the Grid for my custom needs. To keep it short (sorry for those of you who didn&#8217;t get in touch with the Grid so far <img src='http://techblog.molindo.at/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> ), I let my Guestbook implement the GridModelProvider interface, subclassed GridRows in order to be able to use the  a different template-html without losing the GridRows&#8217;s functionality and did the same with the GridPager component.<br />There it was, the Guestbook &#8211; a BeanEditForm above with GridRows and a GridPager below. All it needed now was to override the onSubmit method (or to use the @OnEvent(value = &#8220;submit&#8221;) annotation) to do with the new entry whatever I wanted.</p>
<p>But after all, it just didn&#8217;t feel right to abuse the Grid and to call that my &#8220;custom component&#8221;. I think I&#8217;ll never use it in a real-life application, but I got a good insight into how components work in Tapestry5 by playing with those two. Here my two pennies worth on the whole stuff:</p>
<p>The &#8216;mighty&#8217; components in Tapestry5 seem to be hard to extend &#8211; maybe it is better to use them as they are, without trying to combine them to form a new component (which might be what the developers wanted). I believe that it wouldn&#8217;t be too difficult to create mighty components on your own, if you already created some small components. There were two little things I noticed during dealing with the GridPager component:
<ul>
<li>The GridPager component shouldn&#8217;t be limited to the Grid. In its current state it requires a GridDataSource object, which actually is the only link to the Grid. Basically it&#8217;s just a matter of a different naming. Thus creating a super-interface of GridDataSource (e.g. DataSource with the method getNrOfItems():int) would make the GridPager reusable for other components without having the Grid-stuff in it.</li>
</ul>
<ul>
<li>The CSS-class shouldn&#8217;t be hard-coded. Overriding the css would be a possibility, but it would look much neater to pass it as a parameter.</li>
</ul>
<p>Well, that&#8217;s all for today. I&#8217;d love to hear about your experience with creating your custom components. So if you have something to say, or questions, just leave a comment below!</p>
<p>Unfortunately I did not find the time to look a bit more into <a href="http://maven.apache.org/">Maven</a>. Now even Tapestry creator Howard Lewis Ship swears like a trooper in his <a href="http://tapestryjava.blogspot.com/2007/08/maven-love-to-hate-or-hate-to-love.html">recent blog entry</a> <img src='http://techblog.molindo.at/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> . I&#8217;ll definitely have to take a more thorough look into Maven &#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://techblog.molindo.at/2007/08/creating-custom-components-with-tapestry-5.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

