<?xml version="1.0"?>
<rss version="2.0"  xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<atom:link href="http://dev.day.com/microsling/content/blogs/main.xml" rel="self" type="application/rss+xml" />
<title>(content goes here) blog</title>
<description>(content goes here) blog</description>
<link>http://dev.day.com/microsling/content/blogs/main.html</link>



	<item>
	<title>[LOTD] JCR in the sky</title>	
	<link>http://dev.day.com/microsling/content/blogs/main/lotd20080825.html</link>
	<guid>http://dev.day.com/microsling/content/blogs/main/lotd20080825.html</guid>
	<description><![CDATA[<p>Storing data within <a href="http://en.wikipedia.org/wiki/Cloud_computing">the cloud</a> (<a href="http://www.trackvia.com/blog/?p=45">formerly known as SaaS, the elderly might even remember ASP</a>) is the latest craze. If you want to jump on that bandwaggon or simply have a lot of files check out Scott Dietrich's Jackrabbit DataStore for <a href="http://www.amazon.com/gp/browse.html?node=16427261">Amazon S3</a>. Scott has <a href="http://markmail.org/message/iny24qxsieutfzeq">posted a link to the sources</a> on the Jackrabbit user list.</p>]]></description>
	<pubDate>25 undefined 2008 00:00:01 GMT</pubDate>
	<author>dev@day.com (Michael Marth)</author>
	
			<category>link of the day</category> <category>jackrabbit</category> <category>jcr</category> 	
	
	</item>
	
	<item>
	<title>Sling is an evolutionary step for WCMSs</title>	
	<link>http://dev.day.com/microsling/content/blogs/main/evolution.html</link>
	<guid>http://dev.day.com/microsling/content/blogs/main/evolution.html</guid>
	<description><![CDATA[<p>
<a href="http://dev.day.com/microsling/content/blogs/main/cq5beta2.html">Communique 5</a> is currently being built on top of Apache Sling. I believe this is a step forward in the overall architectural evolution of web content management systems because it exposes a new type of interface to developers of content centric applications: the web infrastructure layer. Let me explain this idea in the context of CMS history:
</p>

<h4>1. The Big Blob</h4>

<p>
Seen from a developer's perspective early CMSs came along as one big piece of software . If you wanted to develop custom applications with them you usually had to develop on top of the CMS API. This API for WCMS would contain abstractions like "paragraph", "user" or "workflow" and expose actions like "publish a page", i.e. the abstraction level was the level of the WCMS business logic (I use the term "business logic" as in "the business of managing content"). For the purpose of this argument, let's call these APIs the "business level API".
</p>

<p><img src="/microsling/content/blogs/main/evolution/docroot/cq51.png"/></p>

<h4>2. Splitting off the repository</h4>

<p>
It was obvious that the content had to be also accessible for developers outside of the context of the business-layer API. Thus, the repository layer was abstracted: a number of CMSs created an API that allowed direct access to the content, either through JCR/JSR-170 or some proprietary API. This gave developers two choices how to access the content: either in the context of the business API or the "raw" access through, say, JCR.
</p>
<p>
Introducing the repository-level API can be seen as a clean architectural cut for a CMS in order to improve <a href="http://en.wikipedia.org/wiki/Separation_of_concerns">separation of concerns</a>.
</p>

<p><img src="/microsling/content/blogs/main/evolution/docroot/cq52.png"/></p>


<h4>3. Splitting off the web infrastructure</h4>

<p>
In this next evolutionary step we take what is left of the WCMS after the repository is split off and separate off another layer: the web infrastrucure (Sling). This layer contains the basic plumbing required to build web apps, e.g. request handling, selecting content, script execution, authentication, filters etc. This leaves the business layer with the business logic only.
</p>

<p><img src="/microsling/content/blogs/main/evolution/docroot/cq53.png"/></p>


<p>
One effect of splitting off the web infrastructure is that developers can write web applications that sit "next to" the WCMS application rather than running on top of the WCMS. This means that these developers do not need to be concerned with (and learn about) the particular CMS business logic because they have <em>access to the web application infrastructure</em> provided by the CMS.
</p>

<p><img src="/microsling/content/blogs/main/evolution/docroot/cq54.png"/></p>


<p>
This is a second architectural cut and separation of concerns that acknowledges that there are different types of content centric applications and WCMS is only one of them (consider forums, blogs, media asset management, wikis, etc). These different content-centric apps share requirements for repositories and web infrastructure, though.
</p>
<p>
It should be noted that compared to the second step above this additional separation of concerns does not really allow you to do anything that was not possible before. However, it is such a big advancement in terms of developer productivity that I consider it to be a qualitative change. (If  you disagree: Try building a web app starting with just a connection to your repository and another one on top of Sling. You will understand.)
</p>

<h4>Some clarifications</h4>

<p>
There are of course myriads of WCMSs already that let developers write extensions or modules or similar. That approach is different though because these applications run "within" the CMS context, i.e. the developer is still interfacing the business layer. On top of Sling, your app is a  <b>first-class</b> citizen just like CQ5.
</p>
<p>
This CMS-oriented view of the world and its history might seem strange if you look from an application server angle: in the app server world the persistence layer, the application framework (Struts, PHP, ...) and the application were always neatly separated - so Sling would be nothing new. However, this is not quite the same situation as step 3 in the CMS world because in the classical web infrastructure world the application framework knows nothing about the underlying repository - usually it just handles database connection pooling or similar. Sling does know about the repository and thus it can provide additional functionality. Therefore, if you want to stay in the classical web infrastructure picture you could regard Sling as a very specialized application framework (specialized for content-centric applications). AFAIK this is a new piece of infrastructure that did not exist before.</p>
]]></description>
	<pubDate>18 undefined 2008 00:00:01 GMT</pubDate>
	<author>dev@day.com (Michael Marth)</author>
	
			<category>cms</category> 	
	
	</item>
	
	<item>
	<title>Javamagazin</title>	
	<link>http://dev.day.com/microsling/content/blogs/main/javamagazin.html</link>
	<guid>http://dev.day.com/microsling/content/blogs/main/javamagazin.html</guid>
	<description><![CDATA[<p>If you happen to live in Germany, Switzerland or Austria (and speak German) make sure you do not miss <a href="http://it-republik.de/jaxenter/java-magazin-ausgaben/Was-ist-Content%3F-000265.html">this month's Javamagazin</a>. The title story is "Was ist Content?" ("what is content?") and there is also an introductory article about JCR and Apache Jackrabbit.
</p>

<p><a href="http://it-republik.de/jaxenter/java-magazin-ausgaben/Was-ist-Content%3F-000265.html"><img src="/microsling/content/blogs/main/javamagazin/docroot/JM.jpg"/></a></p>

<h4>The abstracts:</h4>

<p>
<b>Was ist Content?</b><br><br>

Bilder, Videos, Texte – man erkennt Content, wenn man ihn sieht. Aber hat Content charakteristische Eigenschaften, die ihn von reinen Daten unterscheiden? In Gesprächen über Content und Content-Management ist gelegentlich festzustellen, dass Content mit relationalen Datenbanken oder Dateisystemen gleich gesetzt wird. Obwohl Content letzten Endes oft im Dateisystem oder einer Datenbank gespeichert wird, wird eine Reduktion auf diese Low-Level-Sicht der Thematik nicht gerecht. Content ist eine spezielle Form von Daten, denen eine eigene Qualität innewohnt. Insofern ist auch Content-Management mehr als nur eine Datenbankmaske.<br>
<i>David Nüscheler, Michael Marth</i>
</p>
<p>
<b>JCR und Apache Jackrabbit</b><br><br>

Der JCR-Standard (Content Repository API for Java) beschreibt eine klare Schnittstelle zwischen Anwendung und Content-Ablage. Das hierdurch definierte Content Repository stellt die dem Content typischen Eigenschaften und Funktionalitäten in standardisierter Weise zur Verfügung. Dies erleichtert erheblich die systemübergreifende Nutzung von Content und erschließt damit ein bisher nur mit viel Mühen auszuschöpfendes Potenzial.<br>
<i>Michael Marth, Gerd Handke, David Nüscheler, Carsten Ziegeler</i>
</p>]]></description>
	<pubDate>14 undefined 2008 00:00:01 GMT</pubDate>
	<author>dev@day.com (Michael Marth)</author>
	
			<category>everything is content</category> 	
	
	</item>
	
	<item>
	<title>Implementing OpenSearch in 10 Minutes</title>	
	<link>http://dev.day.com/microsling/content/blogs/main/opensearch.html</link>
	<guid>http://dev.day.com/microsling/content/blogs/main/opensearch.html</guid>
	<description><![CDATA[<p>
One of the productivity-boosting features of <a href="http://en.wikipedia.org/wiki/Content_repository_API_for_Java">JCR</a> is the included search engine (which is <a href="http://lucene.apache.org/">Apache Lucene</a> in case of <a href="http://jackrabbit.apache.org/">Jackrabbit</a> and <a href="http://www.day.com/content/site/en/index/solutions/content-centric_infrastructure/content_repository.html">CRX</a>). This feature can be used to very quickly develop an <a href="http://www.opensearch.org/Home">OpenSearch</a> interface for a <a href="http://incubator.apache.org/sling/site/index.html">Sling</a>-based application.
</p>
<p>
I have recently <a href="http://dev.day.com/microsling/content/blogs/main/anothersampleapp.html">provided a Sling example application called Notes</a> which I want to use to demonstrate the implementation of OpenSearch. Import the Notes application into your CRX Quickstart (<a href="http://dev.day.com/microsling/content/blogs/cup/downloads.c.html">download Quickstart</a> if you do not have it, yet). For importing navigate to http://localhost:7402/crx/index.jsp and start the Package Manager.
</p>
<p>
In OpenSearch search results can be in different formats. Let's start with producing results in XHTML. Add a new file at /apps/notes/opensearch.jsp. It shall contain:
</p>

<div class="codesnippet scrollablecodesnippet">
<pre>&lt;?xml version="1.0" encoding="UTF-8"?>
&lt;%@page import="javax.jcr.query.*, javax.jcr.*"%>
&lt;%@taglib prefix="sling" uri="http://sling.apache.org/taglibs/sling/1.0"%>
&lt;sling:defineObjects/>
&lt;%@ include file="/apps/notes/util.jsp" %>
&lt;%
String q = "/jcr:root/content/notes//*["+ SearchUtils.parameterToQuery(request.getParameter("qt")) +"]";
Query query = currentNode.getSession().getWorkspace().getQueryManager().createQuery(q, "xpath");
NodeIterator result = query.execute().getNodes();
%>
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
&lt;html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
  &lt;head profile="http://a9.com/-/spec/opensearch/1.1/" >
    &lt;title>Notes app search results&lt;/title>
    &lt;link rel="search" type="application/opensearchdescription+xml" href="http://localhost:7402/apps/notes/opensearch" title="Notes Search" />
    &lt;meta name="&lt;%=result.getSize()%>" content="4230000"/>
    &lt;link rel="stylesheet" href="/apps/notes/static/blue.css">
  &lt;/head>&lt;body>
    &lt;div id="Header">&lt;a href="/content/notes.html">&lt; back to thread overview&lt;/a>&lt;/div>&lt;div id="Content">
    &lt;h1>search results for query &lt;%=request.getParameter("qt") %>, hits: &lt;%=result.getSize()%>&lt;/h1>&lt;ul>&lt;%@ include file="/apps/notes/searchBox.jsp" %>&lt;ul>
&lt;%
while(result.hasNext()) {
  Node n = result.nextNode();
  String t = n.getProperty("body").getValue().getString();
%>		
    &lt;li>
    &lt;a href="http://localhost:7402&lt;%=n.getPath()%>.thread.html">&lt;%=t.length() > 50 ? t.substring(0,50) + "..." : t%>&lt;/a>
    &lt;div>&lt;p>&lt;%=t%>&lt;/p>&lt;/div>
    &lt;/li>
&lt;%}%>		
&lt;/ul>&lt;/div>&lt;/body>&lt;/html>
</pre></div>
<p>
There is only a few OpenSearch-related lines like the link to the OpenSearch descriptor file (explained further below)
</p>
<div class="codesnippet scrollablecodesnippet">
<pre>
&lt;link rel="search" type="application/opensearchdescription+xml" href="http://localhost:7402/apps/notes/opensearch" title="Notes Search" />
</pre></div>
<p>
and the META tag that describes the result set:
</p>
<div class="codesnippet scrollablecodesnippet">
<pre>
&lt;meta name="&lt;%=result.getSize()%>" content="4230000"/>
</pre></div>
<p>
The rest of this jsp is just using the standard JCR-provided query functionality to produce standard XHTML. That's it. This is your shiny new OpenSearch interface (I need to stress this once more because it's really cool: no search engine crawling or or other setup was needed. Neither was there any JCR-JSP-wiring or other web app configuration). Point your browser to: http://localhost:7402/content/notes.opensearch.html?qt=JCR to have a look (the request parameter qt denotes the query term).
</p>
<p><img src="/microsling/content/blogs/main/opensearch/docroot/xhtml.jpg"/></p>
<p>
The above mentioned descriptor file describes the app's search capabilities to external parties. Given the link element from above it needs to be in /apps/notes/opensearch and shall contain:
</p>
<div class="codesnippet scrollablecodesnippet">
<pre>
&lt;?xml version="1.0" encoding="UTF-8"?>
&lt;OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/" xmlns:moz="http://www.mozilla.org/2006/browser/search/">
  &lt;ShortName>Notes app&lt;/ShortName>
  &lt;Description>Notes app search interface&lt;/Description>
  &lt;Url type="text/html" template="http://localhost:7402/content/notes.opensearch.html?qt={searchTerms}"/>
  &lt;Url type="application/rss+xml" template="http://localhost:7402/content/notes.opensearchrss.xml?qt={searchTerms}"/>
  &lt;Url type="application/x-suggestions+json" template="http://localhost:7402/content/notes.opensearchsuggestions.json?qt={searchTerms}"/>
&lt;/OpenSearchDescription>
</pre></div>
<p>
The first URL element describes the XHTML-based output implemented discussed above. OpenSearch also allows RSS-based output which is described in the second URL-element. The implementation of RSS-based OpenSearch results is even more succinct because there is less boiler-plate code. Create the renderer file /apps/notes/opensearchrss.xml.jsp and let it contain:
</p>
<div class="codesnippet scrollablecodesnippet">
<pre>
&lt;?xml version="1.0" encoding="UTF-8"?>
&lt;rss version="2.0" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/">
&lt;%@page import="javax.jcr.query.*, javax.jcr.*"%>
&lt;%@taglib prefix="sling" uri="http://sling.apache.org/taglibs/sling/1.0"%>
&lt;sling:defineObjects/>
&lt;%@ include file="/apps/notes/util.jsp" %>
&lt;%
String q = "/jcr:root/content/notes//*["+ SearchUtils.parameterToQuery(request.getParameter("qt")) +"]";
Query query = currentNode.getSession().getWorkspace().getQueryManager().createQuery(q, "xpath");
NodeIterator result = query.execute().getNodes();
%>
&lt;channel>
  &lt;title>Local Notes app&lt;/title>
  &lt;link>http://localhost:7402/content/notes.html&lt;/link>
  &lt;description>Search results for "&lt;%=request.getParameter("qt") %>" at the local Notes app&lt;/description>
  &lt;opensearch:totalResults>&lt;%=result.getSize()%>&lt;/opensearch:totalResults>
&lt;%
while(result.hasNext()) {
	Node n = result.nextNode();
%>
  &lt;item>
    &lt;% String t = n.getProperty("body").getValue().getString(); %>
    &lt;title>&lt;%=t.length() > 50 ? t.substring(0,50) + "..." : t%>&lt;/title>
    &lt;link>http://localhost:7402&lt;%=n.getPath()%>.thread.html&lt;/link>
    &lt;description>&lt;%=t%>&lt;/description>
  &lt;/item>
&lt;%}%>
&lt;/channel>&lt;/rss>
</pre></div>
<p>
Hit http://localhost:7402/content/notes.opensearchrss.xml?qt=JCR with your browser or any other RSS viewer to retrieve the search results in RSS format.
</p>

<p><img src="/microsling/content/blogs/main/opensearch/docroot/rss.jpg"/></p>

<p>
OK, this is simple to implement, but what is it good for? For example, <a href="http://www.opensearch.org/Community/OpenSearch_search_clients">recent browsers</a> support autodiscovery of OpenSearch engines and allow users to add them to the browser's upper right search box. Simply add a link in the HTML page's header:
</p>
<div class="codesnippet scrollablecodesnippet">
<pre>
&lt;link rel="search" type="application/opensearchdescription+xml" title="Notes" href="http://localhost:7402/apps/notes/opensearch">
</pre></div>
<p>
I have tested this in IE7 and FF2:
</p>

<p><img src="/microsling/content/blogs/main/opensearch/docroot/ie.jpg"/></p>
<p><img src="/microsling/content/blogs/main/opensearch/docroot/ff.jpg"/></p>

<h4>Search Suggestions</h4>


<p>
There is an <a href="http://www.opensearch.org/Specifications/OpenSearch/Extensions/Suggestions/1.0">enhancement suggested for upcoming versions of OpenSearch that would standardize search suggestions</a>. In Firefox, however, a <a href="http://developer.mozilla.org/en/docs/Supporting_search_suggestions_in_search_plugins">similar feature is already implemented</a>. The third URL in the descriptor file describes the interface for search suggestions in FF (i.e. this will not work in IE). The corresponding implementation at /apps/notes/opensearchsuggestions.json.jsp looks like this:
</p>
<div class="codesnippet scrollablecodesnippet">
<pre>
&lt;%@page import="javax.jcr.query.*, javax.jcr.*, java.util.*"%>
&lt;%@taglib prefix="sling" uri="http://sling.apache.org/taglibs/sling/1.0"%>
&lt;sling:defineObjects/>
&lt;%@ include file="/apps/notes/util.jsp" %>
&lt;%
// Hashmap to collect and count full words that contain the query term
TreeSet&lt;String> collector = new TreeSet();

// only accept min 2 char strings and does not end with a blank
if((request.getParameter("qt").length() > 1) && !(request.getParameter("qt").endsWith(" "))) {

// the actual search
String q = "/jcr:root/content/notes//*[" + SearchUtils.parameterToSuggestionQuery(request.getParameter("qt")) + "]";
Query query = currentNode.getSession().getWorkspace().getQueryManager().createQuery(q, "xpath");
NodeIterator result = query.execute().getNodes();

// the constant part of the suggestions
String constantPart = "";
String[] requestTokens = request.getParameter("qt").split("\\s");  
for (int x=0; x&lt;requestTokens.length - 1; x++) constantPart += requestTokens[x] + " ";

// we need to see what the actual word was where the search result occurred
while(result.hasNext()) {
  Node n = result.nextNode();
  String[] tokens = n.getProperty("body").getValue().getString().split("\\s");  
  for (int i=0; i&lt;tokens.length; i++) if(tokens[i].toLowerCase().contains(requestTokens[requestTokens.length-1].toLowerCase())) collector.add(tokens[i]);
}

// print result
// format is e.g. ["fi", ["firefox", "first", "fist"]]
%>["&lt;%=request.getParameter("qt")%>", [&lt;%
boolean first = true;
Iterator results = collector.iterator();
while(results.hasNext()) { %>
  &lt;%=!first?", ":""%>"&lt;%=constantPart + results.next()%>"
  &lt;% first = false; }%> ]]
&lt;%} else { // if the query term is only 1 char long%>
["&lt;%=request.getParameter("qt")%>",[]]
&lt;%}%>
</pre></div>
<p>
As the jsp's file name suggests the jsp returns json-formatted data. The returned data is a collection of suggestions based on the actual content (i.e. suggesting words that would produce hits). The format for a query "fi" must be of the form ["fi", ["firefox", "first", "fist"]]. Most of the code deals with String manipulation which is a bit verbose in Java. Also, I wanted to have multi-word queries like "jcr re" return suggestions for the last word only (i.e. ["jcr re", ["jcr repository", "jcr renderer"]]) which requires a couple of additional lines of code.
</p>
<p><img src="/microsling/content/blogs/main/opensearch/docroot/ffs.jpg"/></p>
<p>
As usual, the full application including the complete sources is attached to this post in CRX Package Manager format.
</p>]]></description>
	<pubDate>12 undefined 2008 00:00:01 GMT</pubDate>
	<author>dev@day.com (Michael Marth)</author>
	
			<category>sling</category> <category>tutorial</category> <category>open</category> <category>rad</category> 	
	
	</item>
	
	<item>
	<title>Roy Fielding's OSCON talk about Open Architecture</title>	
	<link>http://dev.day.com/microsling/content/blogs/main/royoscon.html</link>
	<guid>http://dev.day.com/microsling/content/blogs/main/royoscon.html</guid>
	<description><![CDATA[<p>
<a href="http://www.day.com/site/en/index/company/company_overview/management.html">Day's Chief Scientist Roy Fielding</a> gave a talk about <a href="http://roy.gbiv.com/talks/200807_OpenArch_OSCON.pdf">Open Architecture</a> at this year's <a href="http://en.oreilly.com/oscon2008/public/content/home">OSCON</a>. Roy specifically looks at Peyman Oreizy's thesis titled "<a href="http://www.ics.uci.edu/~peymano/">Open Architecture Software: A Flexible Approach to Decentralized Software Evolution</a>". Find the slides below:
</p>

<div style="text-align: center;">
<a href="http://roy.gbiv.com/talks/200807_OpenArch_OSCON.pdf">
<img src="http://dev.day.com/microsling/content/blogs/main/royoscon/docroot/r.png"/>
</a>
</div>
<br/>]]></description>
	<pubDate>05 undefined 2008 00:00:01 GMT</pubDate>
	<author>dev@day.com (Michael Marth)</author>
	
			<category>open</category> 	
	
	</item>
	
	<item>
	<title>Ask the community: Brix</title>	
	<link>http://dev.day.com/microsling/content/blogs/main/brix2.html</link>
	<guid>http://dev.day.com/microsling/content/blogs/main/brix2.html</guid>
	<description><![CDATA[<p>Recently, I <a href="http://dev.day.com/microsling/content/blogs/main/brix.html">blogged about Brix</a>, which is a new open source cms based on <a href="http://wicket.apache.org/">Apache Wicket</a> and <a href="http://jackrabbit.apache.org/">Jackrabbit</a>. <a href="http://code.google.com/p/brix-cms/">Brix</a> has been developed by the <a href="http://www.inertiabev.com/inertiabev/index.jsp">Inertia Beverage Group</a>. Inertia's Chief Strategy Officer Paul Mabray sat down with the dev team and passed on my questions about JCR and Jackrabbit:
</p>


<p><b>Paul Mabray: So tell me a bit about each of you - your background, hobbies, etc.</b></p>

<p><b>Matej Knopp</b>: Hi, I am Matej. I’m a key independent consultant from Slovakia. My number one project for Inertia is working on Brix and enjoying every minute of it. I’m also an Apache Wicket enthusiast and committer. Obviously I have a severe lack of free time.</p>

<p><b>Paul</b>: Do you do anything else?</p>

<p><b>Matej</b>: Whatever little time I find away from the keyboard I try to read as much as I can.</p>

<p><b>Patrick Angeles</b>: I guess, aside from you Paul, I am the veteran at Inertia.  I am the VP of Technology and lead our SaaS development for a software solution that connects wineries to their customers.  I’ve been in tech for over 10 years working for big companies like Bankers Trust and Acquire Systems.  Food, wine and my family are the only things I have time to do outside of work.</p>

<p><b>Igor Vaynberg</b>: I’m the Principal Software Engineer at Inertia, residing in sunny Sacramento, California.  I’m the guy your brought in to help build the next-generation enterprise web application that help will more easily bridge the gap between wineries and their customers.</p>

<p><b>Paul</b>: Tell me more</p>

<p><b>Igor</b>: Well, my love for writing software was sparked when I received a Sinclair Z80 on my tenth birthday and  I’ve been doing it ever since.  I do have the same hobbies as you such as playing with my kids, taking my beautiful wife to fancy dinners - that should get me points at home - and fragging my friends at Halo.  I also still find time to work on software. My number one  outlet is the Apache Wicket framework - I really believe to be the best way to build web applications.</p>

<p><b>Paul</b>: And I am the founder of Inertia and now Chief Strategy Officer in charge of product development and business development.  Just like Patrick I only have time for the family outside of work.  But I love what I do and when this team brought forth the concept to make Brix open source, I was 200% in support of the initiative.</p>

<p><b>Igor/Patrick</b>: COME ON</p>

<p><b>Paul</b>: OK, I frag a few people on Halo when I get a spare minute.</p>

<p><b>Paul: So Michael asked us a question - Brix uses Apache Jackrabbit as its content repository. Back in the days when you made this decision what potential choices were you considering and what influenced your decision towards Jackrabbit?</b></p>

<p><b>Igor</b>: From the start, one of our major requirements was the ability for our users to edit content using their favorite desktop editor. We picked SVN and JCR as two possible solutions: SVN with its local check-in/check-out, and JCR with its WebDAV support. We started off with SVN because it had more powerful versioning features, such as merging. But we quickly ran into features we needed that were missing and would be too expensive to implement ourselves: referential integrity and ASLv2 java connector library being the two that jump to mind (we were planning to open-source Brix from the start under ASLv2).</p>

<p><b>Patrick</b>: That is why we switched to JCR. Jackrabbit seemed to be the most actively developed and complete JCR implementation, and since it was already released under ASLv2 it was not a very hard choice. A bonus for us is that two of our Brix developers are also Apache committers, and since Inertia is not shy about contributing to open source we saw an opportunity to improve Jackrabbit and give back to its community as we went along.</p>

<p><b>Q: Did your expectations regarding the JCR come true or did you have to overcome some difficulties you did not expect? Were there any pleasant or not so pleasant surprises after working with Jackrabbit for a while?</b></p>

<p><b>Matej</b>: The most pleasant surprise was how much functionality Jackrabbit/JCR brought to the table: indexing, referential integrity, WebDAV, workspaces, versioning, and the list keeps going on. The API is consistent and easy to use.</p>

<p><b>Igor</b>: Don’t forget our experience with Jackrabbit/JCR was not perfect. It seems that the modus operandi of the JCR community is to use a repository with a set small number of workspaces, which did not mesh well with our needs. Brix makes an extensive use of JCR workspaces for multi-site support, site snapshots, and publishing workflow. This means that we needed to create and delete workspaces on the fly as well as have an easy way to search across them via some index.</p>

<p>The first problem we ran into was that workspace creation event was not replicated across the Jackrabbit cluster. We have already patched Jackrabbit to support this feature, the patch is available in Jackrabbit’s issue tracker under <a href="https://issues.apache.org/jira/browse/JCR-1677">JCR-1677</a>.</p>

<p><b>Patrick</b>: The second, and more severe, problem was the way Jackrabbit manages database connections. Currently each Jackrabbit workspace keeps an open connection to the database. We are planning to host over 300 client sites on Brix in the near future. Brix’s publishing workflow requires 3 workspaces per site: development, staging, and production. Without even counting workspaces created for snapshots,  we are up to 900 workspaces and thus 900 open database connections. This simply does not scale. Unfortunately, this does not look like a high priority for the Jackrabbit community, because seeminly the most common usecase is a repository with a small number of workspaces. Nonetheless, we are working on a patch that would allow for connection pooling. A first pass of the patch is available in the Jackrabbit issue tracker under <a href="https://issues.apache.org/jira/browse/JCR-1456">JCR-1456</a>.</p>

<p><b>Q: One often discussed aspect of building content management systems on top of JCRs is the question if object-content-mapping should be used to wrap collections of JCR nodes into application-level objects. What is your view on this question?</b></p>

<p><b>Igor</b>: Brix’s object model is very simple, so using some kind of object-content mapping would have been overkill for us. We do have a wrapper for the JCR api, but that was meant for other things (<em>see below</em>).</p>

<p><b>Q: In Brix you have wrapped JCR nodes and sessions in Brix' own wrapper classes. In the wrappers API calls are intercepted and events are generated. Why was this design decision made rather than using JCRs native Observation mechanisms?</b></p>

<p><b>Patrick</b>: Our JCR API wrapper is two levels deep.</p>

<p>The bottom layer is an event layer. It provides events for before and after a change, as well as an ability to queue the events in a list and batch process them later. We also group and normalize the events so it is possible to know what is about to be changed <b>before</b> the change is applied. JCR’s native observation mechanism is limited to only observing changes that have already happened.</p>

<p><b>Matej</b>: The top wrapper has two basic jobs:</p>

<p>Translate JCR’s checked exception model into unchecked while providing a pluggable and centralized way for exception handling strategies. In OOP JCR code is sprinkled among many classes, the checked exception model becomes extremely viral. Also, since a lot of exceptions are unrecoverable from Brix’s perspective there is very little point of having them be checked.</p>

<p>The second job of this wrapper is to allow node wrapping. Instead of using a full blown and complex object-content-mapping system we provide a simple mechanism for having nodes wrapped based on their brix:nodeType property. This makes it possible to write code like this:</p>

<p>
<div class="codesnippet scrollablecodesnippet"><pre>
Node n = session.getRootNode().getNode("page.html");
PageNode page = (PageNode) n;
page.setTitle("Page Title");
page.setMarkup("Page Content");
</pre></div>
</p>

<p><b>Q: Brix' WebDAV server has the nice feature that uploaded resources are automatically converted into Brix artifacts. How does that work?</b></p>

<p><b>Igor</b>: This is done by intercepting node events using the aforementioned wrapper and modifying the nodes before they are saved based on rules defined in Brix. There is also some magic to handle varying WebDAV client behaviors, for example: when a new file is created via Coda it will first create an Untitled file and immediately rename it to its given name.</p>

<p><b>Q:If you had one wish regarding JCR and the JCR community, what would it be?</b></p>

<p><b>Patrick</b>: We would wish the JCR community a very long and productive future.</p>

<p><b>Paul</b>: I hope that the JCR community sees Brix as useful piece of software and contributes to its health and success.</p>]]></description>
	<pubDate>31 Jul 2008 00:00:01 GMT</pubDate>
	<author>dev@day.com (Michael Marth)</author>
	
			<category>ask the community</category> <category>jcr</category> 	
	
	</item>
	
	<item>
	<title>CQ5 status update: tech preview completed</title>	
	<link>http://dev.day.com/microsling/content/blogs/main/cq5beta2.html</link>
	<guid>http://dev.day.com/microsling/content/blogs/main/cq5beta2.html</guid>
	<description><![CDATA[<p>
Here's a brief update on Communique 5's delivery: we are in excellent shape and the quality gated approach is paying of for our customers.
</p><p>
As it was laid out in <a href=""http://dev.day.com/microsling/content/blogs/main/cq5beta.html>a previous post</a> there are two iterations we need to go through before we release CQ5: the tech preview phase and the beta program. I am very happy to report that the tech preview has been successfully completed. By now, the beta program has started. I'm excited to see the shine in the developers eyes when they are allowed to take this baby into their hands.
</p><p>
The customer who completed the tech preview with us is now in production with CQ5. There are about 80 editors producing content already. This number is expected to increase into several hundred very soon. This is a fantastic success, but there are also other ("softer") factors that we have experienced during the tech preview project. Both, the editors as well as the developers perceive working with CQ5 to be very pleasant and exciting compared to the competing products they knew. I am extremely happy about this feedback as it goes to show that our efforts on user experience and software architecture were well invested.
</p><p>
There is also another interesting by-product of the beta program: by the time the program is finished most of our service and support team will have real-life experience with CQ5 from real-life customers in production. So from day one of the product launch there will be experienced service and support resources available from Day.
</p>]]></description>
	<pubDate>31 Jul 2008 00:00:01 GMT</pubDate>
	<author>dev@day.com (Jean-Michel Pittet)</author>
	
			<category>communique</category> <category>cms</category> 	
	
	</item>
	
	<item>
	<title>Sling Applications and Relational Databases</title>	
	<link>http://dev.day.com/microsling/content/blogs/main/slinglegacydata.html</link>
	<guid>http://dev.day.com/microsling/content/blogs/main/slinglegacydata.html</guid>
	<description><![CDATA[<p>
One topic that periodically comes up is how to integrate data that resides relational databases with a Sling application. The use case might be that there is legacy data that cannot be migrated but needs to displayed in a new (Sling-based) web application. In this post I would like to discuss some aspects and possible strategies to accomplish this goal.
</p>
<p>
One essential question for determining a fitting integration strategy is if the db rows shall be exposed as resources (in the REST sense). Let us start with the case that they shall not be exposed as resources. In such a scenario a db row does not have its own URL. A typical Sling application in such a scenario would expose the JCR-based content as resources, but might add data from the db to the presentation of the resources.
</p>
<p>
On a technical level this could be implemented by creating an OSGi bundle that uses JDBC to connect to the database. The bundle would then be called by the rendering script through an OSGi service interface (as described <a href="http://dev.day.com/microsling/content/blogs/main/slingosgi.html">here</a>).
</p>
<p>
However, this approach cannot be used if the db rows shall be exposed as resources and have their own URL.
</p>
<p>
For data that changes on low frequencies one can create a JCR node for each db row. This requires the ability to keep the db and the JCR in sync. The JCR nodes could contain the primary key of the db data. Synching can be achieved by any programm capable of JCR and JDBC.
</p>
<p>
One seemingly obvious way to avoid having to synch is to create a dummy node that represents all of the db data. However, the resulting URLs would not be resource-oriented at all since you need to pass the resource identifier as a request parameter.
</p>
<p>
The full monty and best solution for making your db URLs RESTful is to create a Sling ResourceProvider. This would be an OSGi bundle that claims a part of the URL space in Sling and maps the URLs to resources of whatever kind. In the Sling samples there is an example implementation for file systems. In this example a tree of the local file system is mapped onto the URL space and all files are given Sling resource types. As such, the normal mechanisms for rendering requests are used. The same can be achieved with db rows, of course.
</p>
<p>
It should be noted that there is a generic problem when the relational data needs to be mapped onto the hierarchical URL space. You could go the brute force way of using /content/tablename/id. However, if your data is somehow categorized using many-to-one relationships consider "denormalizing" the data (mentally - you do not need to actually change the tables). This would yield nicer URLs like /content/category1/category2/data (e.g. like /content/wagons/mercedes/e-class).
</p>]]></description>
	<pubDate>30 Jul 2008 00:00:01 GMT</pubDate>
	<author>dev@day.com (Michael Marth)</author>
	
			<category>sling</category> 	
	
	</item>
	
	<item>
	<title>Red Red Wine (JCR Edition)</title>	
	<link>http://dev.day.com/microsling/content/blogs/main/brix.html</link>
	<guid>http://dev.day.com/microsling/content/blogs/main/brix.html</guid>
	<description><![CDATA[<p>
David Nuescheler has a slide that compares JCR-based applications to an iceberg (see e.g <a href="http://dev.day.com/microsling/content/blogs/main/jazoon08pres1.html">here</a>, first presentation, slides 18 and 19). No, not in the sense that it will sink the <a href="http://en.wikipedia.org/wiki/RDBMS">Titanic</a>, but in the sense that the visible part is only a small fraction. Well, proving things that are hidden by definition is often a bit tricky. In the case of JCR-based apps one can refer to the <a href="http://jackrabbit.markmail.org/search/?q=list%3Aorg.apache.jackrabbit.users">traffic on the Jackrabbit user list</a> or the <a href="http://people.apache.org/~vgritsenko/stats/projects/jackrabbit.html#Downloads-N1008F">number of Jackrabbit downloads</a>.
</p>
<p>
But once in a while one can actually look at a previously hidden JCR application: a couple of days ago the JCR-based CMS "Brix" has been <a href="http://code.google.com/p/brix-cms/">open-sourced</a>. It is based on <a href="http://wicket.apache.org/">Wicket</a> and <a href="http://jackrabbit.apache.org/">Jackrabbit</a>. From <a href="http://blog.inertiabev.com/index.php/2008/07/23/brix-released-as-an-open-source-project/">what I understand</a> its origins are in online wine sales (note to self: next time ask for a content sample before posting).
</p>
<p>
In their own words:
</p>

<div class="blockquote">
<p>
Using Apache Wicket as the technology to serve the content makes it very easy to embed custom, stateful Wicket components into any CMS page, allowing rich integration with existing Wicket web application. Using Apache Jackrabbit allows Brix to easily integrate full text search, versioning, and WebDav access.
</p>
</div>

<p>Thanks for making this available, guys.</p>]]></description>
	<pubDate>28 Jul 2008 00:00:01 GMT</pubDate>
	<author>dev@day.com (Michael Marth)</author>
	
			<category>jcr</category> <category>cms</category> 	
	
	</item>
	
	<item>
	<title>Screencast: JCR Connector for MS Sharepoint</title>	
	<link>http://dev.day.com/microsling/content/blogs/main/sharepoint.html</link>
	<guid>http://dev.day.com/microsling/content/blogs/main/sharepoint.html</guid>
	<description><![CDATA[<p>
Here's a 3 minute screencast about Day's JCR Connector for MS Sharepoint (which makes available Sharepoint servers as JCR-compliant repositories). If you need your Java apps to retrieve content from your corporation's Sharepoint servers: this is for you.
</p>


<div style="text-align: center;">


<a href="http://dev.day.com/microsling/content/blogs/main/sharepoint/docroot/sp.html">
<img src="http://dev.day.com/microsling/content/blogs/main/sharepoint/docroot/sp.png"></a>


</div>
<br/><br/>]]></description>
	<pubDate>24 Jul 2008 00:00:01 GMT</pubDate>
	<author>dev@day.com (Michael Marth)</author>
	
			<category>crx</category> <category>screencast</category> 	
	
	</item>
	
<pubDate>25 undefined 2008 00:00:01 GMT</pubDate>
</channel>
</rss>