<?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; Compass</title>
	<atom:link href="http://techblog.molindo.at/category/java/compass/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>Talk On Tech now Molindo Techblog</title>
		<link>http://techblog.molindo.at/2009/01/talk-on-tech-now-molindo-techblog.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=talk-on-tech-now-molindo-techblog</link>
		<comments>http://techblog.molindo.at/2009/01/talk-on-tech-now-molindo-techblog.html#comments</comments>
		<pubDate>Fri, 23 Jan 2009 10:00:24 +0000</pubDate>
		<dc:creator>Stefan Fußenegger</dc:creator>
				<category><![CDATA[Compass]]></category>
		<category><![CDATA[SVN]]></category>
		<category><![CDATA[Wicket]]></category>
		<category><![CDATA[Wordpress]]></category>

		<guid isPermaLink="false">http://tech.molindo.at/?p=84</guid>
		<description><![CDATA[Talk On Tech (talk-on-tech.blogspot.com &#8211; the tech blog you truly love, don&#8217;t you?) was our nice, green home since August 2007. Now, after 1.5 years it was time to move on &#8230; Well, okay, we just want to consolidate all our blogs on a single self-hosted platform. In the course of doing that, we also [...]]]></description>
			<content:encoded><![CDATA[<p>Talk On Tech (talk-on-tech.blogspot.com &#8211; the tech blog you truly love, don&#8217;t you?) was our nice, green home since August 2007. Now, after 1.5 years it was time to move on &#8230; Well, okay, we just want to<a href="http://tech.molindo.at/2008/12/virtual-wordpress-hosts-made-easy.html"> consolidate all our blogs on a single self-hosted platform</a>. In the course of doing that, we also changed the name from Talk on Tech (Let&#8217;s create a blog! How do we name it? What about &#8220;Talk on Tech&#8221;? Yeah, that name is free!) to Molindo Techblog (where Molindo is the name of <a href="http://www.molindo.at/">our very own startup</a>).</p>
<p>If it comes to new posts, We have a lot of ideas but not enough time to elaborate them all. Some ideas are:<br />
<span id="more-84"></span></p>
<ul>
<li>An easy to use <a title="Wicket" href="http://wicket.apache.org">Wicket</a> component for advanced Google Analytics (Outgoing link tracking, search tracking, AJAX events tracking, user defined variables, &#8230;)</li>
<li>Faster batch indexing for <a title="Compass Project" href="http://compass-project.org/">Compass</a></li>
<li>Managing <a title="Subversion" href="http://subversion.tigris.org/">Subversion</a> user access privileges with <a title="Drupal" href="http://drupal.org/">Drupal</a> &#8211; and probably how to move to WordPress afterwards <img src='http://techblog.molindo.at/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </li>
<li>Wicket <a title="Blueprint CSS Framework" href="http://www.blueprintcss.org/">Blueprint</a> integration</li>
<li>How to apply some on-site SEO with a little help of Wicket</li>
<li>Unleashing the full power of Wicket with <a title="Cometd project" href="http://cometdproject.dojotoolkit.org/">Cometd</a> using <a title="wicketstuff-dojo-1.1" href="http://wicketstuff.org/confluence/display/STUFFWIKI/wicketstuff-dojo-1.1">wicketstuff-dojo-1.1</a> and <a title="&quot;Wicket: Loose Coupling of Componens for Ajax Updates&quot; on Molindo Techblog" href="http://tech.molindo.at/2008/09/wicket-loose-coupling-of-componens-for-ajax-updates.html">loose coupling of components</a>.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://techblog.molindo.at/2009/01/talk-on-tech-now-molindo-techblog.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

