<?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>Blue Fish Development Group</title>
	<atom:link href="http://www.bluefishgroup.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.bluefishgroup.com</link>
	<description>Blue Fish Development Group</description>
	<lastBuildDate>Tue, 14 May 2013 19:55:13 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>Please Welcome Our Newest Partner— Crafter Software</title>
		<link>http://www.bluefishgroup.com/2013/please-welcome-our-newest-partner-crafter-software/</link>
		<comments>http://www.bluefishgroup.com/2013/please-welcome-our-newest-partner-crafter-software/#comments</comments>
		<pubDate>Tue, 07 May 2013 21:15:11 +0000</pubDate>
		<dc:creator>Jeff Philipp</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Web Content Management]]></category>
		<category><![CDATA[crafter engine]]></category>
		<category><![CDATA[Crafter Software]]></category>
		<category><![CDATA[crafter studio]]></category>
		<category><![CDATA[WCM]]></category>
		<category><![CDATA[web content management]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/?p=916</guid>
		<description><![CDATA[Blue Fish is excited to announce our newest partner, Crafter Software. Crafter Software offers web content and web experience management software that enable business users to author, manage and deliver content tailored to end users through multiple online channels. We are excited because our clients have long sought a full WCM solution that provides both a [...]]]></description>
				<content:encoded><![CDATA[<p><a href="http://www.bluefishgroup.com/wp-content/uploads/2013/05/partner_crafter_home.png"><img class="alignright size-full wp-image-927" alt="partner_crafter_home" src="http://www.bluefishgroup.com/wp-content/uploads/2013/05/partner_crafter_home.png" width="144" height="110" /></a>Blue Fish is excited to announce our newest partner, Crafter Software. Crafter Software offers web content and web experience management software that enable business users to author, manage and deliver content tailored to end users through multiple online channels.<br />
<br />
We are excited because our clients have long sought a full WCM solution that provides both a great experience for business users, content editors and marketers, combined with robust enterprise-class content management on the back end.  Until now that really didn’t exist, but the combination of Crafter Studio, Crafter Engine and <a title="Alfresco" href="http://www.alfresco.com/">Alfresco</a> finally make that a reality.<br />
<br />
Additionally, Crafter’s open source business model and simple subscription pricing structure will be very attractive – particularly to our clients and prospects who are accustomed to traditional WCM/ECM platforms.<br />
<br />
The initial products from Crafter Software that work together to bring great web content authoring, publishing, and personalized content delivery include:</p>
<ul>
<li><a title="Crafter Studio" href="http://www.craftersoftware.com/products/crafter-studio" target="_blank"><strong>Crafter Studio</strong></a>- An authoring and publishing solution that includes user-friendly features for marketers and content editors, including WYSIWYG authoring, in-context preview, workflow, integrated third-party analytics and multi-channel publishing.</li>
<li><a title="Crafter Engine" href="http://www.craftersoftware.com/products/crafter-engine" target="_blank"><strong>Crafter Engine</strong></a>- A high performance content delivery system that provides developers with the foundation for building high performance web and mobile applications. In turn, this enables business users, through Crafter Studio, to create engaging, personalized experiences for end users.</li>
</ul>
<p>To learn more about Crafter Software check out their <a title="Crafter Software Press Release" href="http://www.businesswire.com/news/home/20130507006137/en/Web-Experience-Management-Simplified-Crafter-Software" target="_blank">recent press release</a> or visit their site at <a title="Crafter Software" href="http://www.craftersoftware.com/" target="_blank">www.craftersoftware.com</a>.<br />
<br />
Also, mark your calendar for May 17th. Crafter is hosting an, &#8220;<a title="Crafter Software Webinar" href="https://attendee.gotowebinar.com/register/3634116077816151808" target="_blank">Introduction to Crafter</a>&#8221; webinar. During this <a title="Crafter Software Webinar" href="https://attendee.gotowebinar.com/register/3634116077816151808" target="_blank">one hour event</a>, Russ Danner, VP Products of Crafter Software, will provide a short summary of Crafter&#8217;s features and benefits, followed by a demo of Crafter&#8217;s key capabilities.</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2013/please-welcome-our-newest-partner-crafter-software/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How To Remove the Welcome Banner From the User and Site Dashboards in Alfresco</title>
		<link>http://www.bluefishgroup.com/2013/how-to-remove-the-welcome-banner-from-the-user-and-site-dashboards-in-alfresco/</link>
		<comments>http://www.bluefishgroup.com/2013/how-to-remove-the-welcome-banner-from-the-user-and-site-dashboards-in-alfresco/#comments</comments>
		<pubDate>Fri, 05 Apr 2013 15:16:04 +0000</pubDate>
		<dc:creator>Gary Cox</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Alfresco]]></category>
		<category><![CDATA[alfresco user and site dashboards]]></category>
		<category><![CDATA[remove welcome banner]]></category>
		<category><![CDATA[user and site dashboards alfresco]]></category>
		<category><![CDATA[welcome banner]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/?p=903</guid>
		<description><![CDATA[In this video, Gary shows you how to remove the dynamic Welcome Banner from User and Site dashboards in Alfresco. These changes will hide the banner for both new and existing users.]]></description>
				<content:encoded><![CDATA[<p>In this video, Gary shows you how to remove the dynamic Welcome Banner from User and Site dashboards in Alfresco. These changes will hide the banner for both new and existing users.</p>
<p><iframe width="500" height="281" src="http://www.youtube.com/embed/8nFfW6kW1IE?feature=oembed" frameborder="0" allowfullscreen></iframe></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2013/how-to-remove-the-welcome-banner-from-the-user-and-site-dashboards-in-alfresco/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Media Previews in Alfresco 4.1.x</title>
		<link>http://www.bluefishgroup.com/2013/media-previews-in-alfresco-4-1-x/</link>
		<comments>http://www.bluefishgroup.com/2013/media-previews-in-alfresco-4-1-x/#comments</comments>
		<pubDate>Mon, 25 Mar 2013 16:03:48 +0000</pubDate>
		<dc:creator>Gary Cox</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[alfresco 4.1.x]]></category>
		<category><![CDATA[alfresco share]]></category>
		<category><![CDATA[media previewer]]></category>
		<category><![CDATA[media previews]]></category>

		<guid isPermaLink="false">http://bluefishgroup.wpengine.com/?p=873</guid>
		<description><![CDATA[Gary takes a look at how Media Previews work in Alfresco 4.1.x, and how you can customize the Media Previewer. He shows you a demonstration of how these work, and how you can change the default plugins. Watch now to learn how to add or modify media players in Alfresco 4.1.x. You can see more [...]]]></description>
				<content:encoded><![CDATA[<p>Gary takes a look at how Media Previews work in Alfresco 4.1.x, and how you can customize the Media Previewer. He shows you a demonstration of how these work, and how you can change the default plugins.<br />
<br />
Watch now to learn how to add or modify media players in Alfresco 4.1.x.</p>
<p><iframe width="500" height="281" src="http://www.youtube.com/embed/ci3bSOTszKE?feature=oembed" frameborder="0" allowfullscreen></iframe></p>
<p>
You can see more tips and tricks in our <a href="/resources/videos/">video library</a>!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2013/media-previews-in-alfresco-4-1-x/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to Disable SOLR Tracking in Alfresco</title>
		<link>http://www.bluefishgroup.com/2013/how-to-disable-solr-tracking-in-alfresco/</link>
		<comments>http://www.bluefishgroup.com/2013/how-to-disable-solr-tracking-in-alfresco/#comments</comments>
		<pubDate>Thu, 21 Mar 2013 16:10:29 +0000</pubDate>
		<dc:creator>Terence McDevitt</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Lucene]]></category>
		<category><![CDATA[SOLR]]></category>

		<guid isPermaLink="false">http://bluefishgroup.wpengine.com/?p=875</guid>
		<description><![CDATA[Terence shows you how to disable SOLR tracking in order to help ease migrations of large amounts of content into an Alfresco repository. While working with clients, we&#8217;ve run into some issues with loading large amounts of data. So, we wanted to show you how we&#8217;ve worked around this. Watch now to learn how to [...]]]></description>
				<content:encoded><![CDATA[<p>Terence shows you how to disable SOLR tracking in order to help ease migrations of large amounts of content into an Alfresco repository.<br />
<br />
While working with clients, we&#8217;ve run into some issues with loading large amounts of data. So, we wanted to show you how we&#8217;ve worked around this. Watch now to learn how to disable SOLR tracking.</p>
<p><iframe width="500" height="281" src="http://www.youtube.com/embed/QQ-MxSNe1oI?feature=oembed" frameborder="0" allowfullscreen></iframe></p>
<p>
You can see more tips and tricks in our <a href="/resources/videos/">video library</a>!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2013/how-to-disable-solr-tracking-in-alfresco/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Webinar: Searching for the Right Solution—An Overview of SOLR on Alfresco</title>
		<link>http://www.bluefishgroup.com/2013/webinar-searching-for-the-right-solution-an-overview-of-solr-on-alfresco/</link>
		<comments>http://www.bluefishgroup.com/2013/webinar-searching-for-the-right-solution-an-overview-of-solr-on-alfresco/#comments</comments>
		<pubDate>Thu, 21 Mar 2013 14:52:50 +0000</pubDate>
		<dc:creator>Terence McDevitt</dc:creator>
				<category><![CDATA[Webinars]]></category>
		<category><![CDATA[Alfresco 4.x]]></category>
		<category><![CDATA[Alfresco 4.x architecture]]></category>
		<category><![CDATA[Lucene]]></category>
		<category><![CDATA[search]]></category>
		<category><![CDATA[SOLOR]]></category>
		<category><![CDATA[SOLR index]]></category>

		<guid isPermaLink="false">http://bluefishgroup.wpengine.com/?p=871</guid>
		<description><![CDATA[Are you interested in understanding the technical benefits of moving from Lucene to SOLR? Is your organization in the process of defining an Alfresco 4.x architecture where search will be a primary use case? Do you have large amounts of content that you&#8217;ll be importing into an Alfresco 4.x repository? Have you been struggling with [...]]]></description>
				<content:encoded><![CDATA[<p>Are you interested in understanding the technical benefits of moving from Lucene to SOLR? Is your organization in the process of defining an Alfresco 4.x architecture where search will be a primary use case? Do you have large amounts of content that you&#8217;ll be importing into an Alfresco 4.x repository? Have you been struggling with the administration of your SOLR index? Find out more about SOLR and whether or not it fits into your solution&#8217;s architecture by joining Blue Fish for a webinar.<br />
<br />
In this webinar, Blue Fish will provide a technical overview of SOLR, tips and suggestions on administering SOLR, discuss potential challenges involved with getting a SOLR index up and running and review tradeoffs between Lucene and SOLR. This webinar is primarily targeted to Alfresco administrators and technical architects.<br />
<br />
With Terence McDevitt, Solution Architect—Blue Fish Development Group and Gary Cox, Senior Consultant—Blue Fish Development Group<br />
<br />
<a href="https://alfresco-events.webex.com/ec0606l/eventcenter/recording/recordAction.do?theAction=poprecord&amp;AT=pb&amp;renewticket=0&amp;isurlact=true&amp;recordID=20532077&amp;apiname=lsr.php&amp;rKey=9B215F414C263FCB&amp;format=short&amp;needFilter=false&amp;&amp;SP=EC&amp;rID=20532077&amp;siteurl=alfresco-events&amp;actappname=ec0606l&amp;actname=%2Feventcenter%2Fframe%2Fg.do&amp;rnd=3142355505&amp;entappname=url0108l&amp;entactname=%2FnbrRecordingURL.do">Download now!</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2013/webinar-searching-for-the-right-solution-an-overview-of-solr-on-alfresco/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Case Study: Davis College Migrates to Alfresco Records Management for Improved Accuracy and Scalability</title>
		<link>http://www.bluefishgroup.com/2013/case-study-davis-college-migrates-to-alfresco-records-management-for-improved-accuracy-and-scalability/</link>
		<comments>http://www.bluefishgroup.com/2013/case-study-davis-college-migrates-to-alfresco-records-management-for-improved-accuracy-and-scalability/#comments</comments>
		<pubDate>Tue, 12 Mar 2013 19:47:43 +0000</pubDate>
		<dc:creator>Leighton Hendrick</dc:creator>
				<category><![CDATA[Case Studies]]></category>
		<category><![CDATA[Content Migrations]]></category>
		<category><![CDATA[Alfresco]]></category>
		<category><![CDATA[alfresco records management]]></category>
		<category><![CDATA[Document Indexing Module]]></category>
		<category><![CDATA[migration]]></category>

		<guid isPermaLink="false">http://bluefishgroup.wpengine.com/?p=839</guid>
		<description><![CDATA[Results Replaced Digitech Systems PaperVision and PaperFlow Unlimited users access Improved Scalability Content accuracy through validation Migrated over 30,000 documents Reused existing equipment Expanded records management without incurring additional costs Challenge Located in Toledo, Ohio, Davis College, a private, two-year college, must adhere to state and federal regulations regarding archiving of student records and transcripts. [...]]]></description>
				<content:encoded><![CDATA[<p class="pull-left"><a href="http://bluefishgroup.wpengine.com/wp-content/uploads/2013/03/DavisCollegelogo.jpg"><img class="alignleft size-thumbnail wp-image-841" style="margin: 10px;" alt="Davis College Toledo" src="http://bluefishgroup.wpengine.com/wp-content/uploads/2013/03/DavisCollegelogo-150x150.jpg" width="150" height="150"></a></p>
<div class="pull-right">
<p><strong>Results</strong></p>
<ul class="no-margin-left">
<li>Replaced Digitech Systems PaperVision and PaperFlow</li>
<li>Unlimited users access</li>
<li>Improved Scalability</li>
<li>Content accuracy through validation</li>
<li>Migrated over 30,000 documents</li>
<li>Reused existing equipment</li>
<li>Expanded records management without incurring additional costs</li>
</ul>
</div>
<p><strong>Challenge</strong><br />
Located in Toledo, Ohio, Davis College, a private, two-year college, must adhere to state and federal regulations regarding archiving of student records and transcripts. Eight years ago, Davis College implemented Digitech Systems PaperVision and PaperFlow, document capture and document management technology, to help digitize and electronically store student records.<br />
<br />
Using one dedicated computer and a high-volume scanner, staff scanned and indexed paper documents into TIFF files. Overtime, the college expanded the solution to include other document centric processes, such as time sheets and enrollments. With only one user license, sharing the dedicated computer across departments was a challenge. The system could not easily scale without a significant financial investment by the college.<br />
<br />
Since upgrading the system was cost prohibitive, Davis College researched other content management solutions that would allow them to reuse their existing high-volume scanners and multifunctional printers (MFPs — scan, copy and print in one device). Key requirements included: ease of use; Web access to documents; unlimited user license; easy to scale; metadata support; and affordability.<br />
<br />
<strong>Solution</strong><br />
Alfresco was selected to replace the PaperVision system. Alfresco’s per server licensing model provided the school with unlimited user access and data storage, rich document management functionality and greater flexibility. In addition, it was priced significantly lower than PaperVision’s basic five-user subscription and could scale to meet future archiving demands.<br />
<br />
Development and testing on Alfresco took Davis College seven weeks. The college worked with Alfresco Platinum and Certified partner Blue Fish Development Group to provide support through the implementation and with basic customization such as changing the default date/time format.<br />
<br />
To simplify the scanning and indexing process, the college implemented the Blue Fish Document Indexing Module for Alfresco Share. With the Document Indexing Module, the college scans documents into Alfresco using their existing high speed scanner or departmental MFPs processing the documents in easy-to-use indexing queues. The college can now store and index PDF, GIF, JPEG, Word, Excel, and most other office and image file formats. Once the documents are scanned and indexed, they are moved to one of seven Alfresco Share sites for easy user access and search.<br />
<br />
Davis College worked with Blue Fish to help migrate over 30,000 documents to Alfresco. Blue Fish programmed a CSV import routine to allow the college to move the document indexes and reclassify the image metadata that was exported from previous software.<br />
<br />
Davis College created rules on how indexed data should be represented or formatted (such as dates and social security numbers). This ensures metadata consistency, data accuracy and improves document search. Since this was not available in the previous system, Alfresco identified numerous content indexing errors during the migration. The college is now verifying the information on any highlighted documents with the original paper documentation. Once complete, the school will begin disposing of paper documents in order to free up physical storage space.<br />
<br />
Today, Davis College has added several users as indexers that can scan documents or images from the closest scanner and transfer the documents via a mapped network drive or an FTP client to an Alfresco Share site. The system will automatically convert any TIFF files to PDF. Before storing the document in Alfresco, a custom Java script runs in the background creating a new folder based on the current date and renames the file based on the date and time &#8211; down to the millisecond.<br />
<br />
Users can log into an Alfresco Share site from any browser seamlessly with single sign-on and LDAP authentication. The user opens the Blue Fish Document Indexing Module for Alfresco Share to classify the document with the appropriate metadata. Once complete, the system automatically moves the document to the selected document library where college personnel can access and search for archived records.<br />
<br />
“We have multiple records management needs throughout the college and require a scalable system that makes it easy to scan, index and digitally store information from any department or location across the campus. Not only is Alfresco more affordable, it provides us the flexibility our users and departments require. Information is securely available for users to search from any desktop and we can validate information for accuracy. This is a huge improvement over our previous solutions and we will look for ways to continue expanding our Alfresco implementation,” said Aaron Cowell, Network Administrator at Davis College.<br />
<br />
<strong>Conclusion</strong></p>
<ul>
<li>Archived student records are now searchable and accessible to administrative staff directly from their desktop. No longer do users have to travel to a separate building or dedicated computer to scan or search archived transcripts saving time and resources.</li>
<li>The new system validates that information is entered correctly ensuring data accuracy and consistency.</li>
<li>LDAP integration guarantees that information is only available based on a user’s security permissions.</li>
<li>Users can scan, upload, and indes them from virtually anywhere on campus.</li>
<li>Davis College can expand document archiving to other departments without incurring additional costs.</li>
<li>The current Alfresco repository stores over 20GB of content.</li>
</ul>
<p><strong>What’s Next</strong><br />
The college has expanded the system to include the digital archiving of historical information from its Heritage Center which houses documents, images and news clippings about the college from the past 154 years. The center has one dedicated person who is scanning documents into Alfresco and another team that reviews, indexes and catalogs the information. Soon a portion of the information will be available internally for searching.<br />
<br />
“With the Blue Fish Document Indexing Module for Alfresco Share, it is easy to turn Alfresco into an imaging system. Alfresco provides the scalable repository, while the Document Indexing Module enables you to scan from any MFP directly into Alfresco, creating indexing queues. Clients like Davis College can classify documents with appropriate metadata,” said Jeff Philipp, CEO of Blue Fish Development Group.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2013/case-study-davis-college-migrates-to-alfresco-records-management-for-improved-accuracy-and-scalability/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Webinar: Securing Sensitive Documents To Protect Your Most Important Asset—Your People</title>
		<link>http://www.bluefishgroup.com/2013/webinar-securing-sensitive-documents-to-protect-your-most-important-asset-your-people/</link>
		<comments>http://www.bluefishgroup.com/2013/webinar-securing-sensitive-documents-to-protect-your-most-important-asset-your-people/#comments</comments>
		<pubDate>Thu, 14 Feb 2013 16:37:39 +0000</pubDate>
		<dc:creator>Lisa Hill</dc:creator>
				<category><![CDATA[Webinars]]></category>
		<category><![CDATA[Alfresco]]></category>
		<category><![CDATA[human resources]]></category>
		<category><![CDATA[indexing]]></category>
		<category><![CDATA[routing]]></category>
		<category><![CDATA[workflows]]></category>

		<guid isPermaLink="false">http://bluefishgroup.wpengine.com/?p=790</guid>
		<description><![CDATA[Security is a challenge that all of us face. When it comes to employees and their personal information security plays an even bigger role. Whether it&#8217;s dealing with confidential records, making sure certain forms have the right signatures at the right time, or quickly on-boarding a new hire, having a secure and easy way to [...]]]></description>
				<content:encoded><![CDATA[<p>Security is a challenge that all of us face. When it comes to employees and their personal information security plays an even bigger role. Whether it&#8217;s dealing with confidential records, making sure certain forms have the right signatures at the right time, or quickly on-boarding a new hire, having a secure and easy way to share and automate daily processes is important.<br />
<br />
Join us for a case study on a Human Resources Employee Files Solution where we will see how one client went from pushing paper and managing physical files to consolidating all of this information into a single solution that could be accessed by the right people, at the right time, from anywhere in the country. We&#8217;ll also show you how they are saving time and money by adding automation in indexing and routing of documents on various workflows.<br />
<br />
With Lisa Hill, Director of Client Services &#8211; Blue Fish Development Group<br />
<br />
<a title="Securing Sensitive Documents To Protect Your Most Important Asset—Your People" href="http://www.alfresco.com/events/webinars/securing-sensitive-documents-protect-your-most-important-asset-your-people" target="_blank">Download now!</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2013/webinar-securing-sensitive-documents-to-protect-your-most-important-asset-your-people/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>White Paper: 5 Unexpected Benefits of Open Source Document Management</title>
		<link>http://www.bluefishgroup.com/2013/white-paper-5-unexpected-benefits-of-open-source-document-management/</link>
		<comments>http://www.bluefishgroup.com/2013/white-paper-5-unexpected-benefits-of-open-source-document-management/#comments</comments>
		<pubDate>Mon, 28 Jan 2013 20:03:11 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[White Papers]]></category>
		<category><![CDATA[document management]]></category>
		<category><![CDATA[open source document management]]></category>

		<guid isPermaLink="false">http://bluefishgroup.wpengine.com/?p=735</guid>
		<description><![CDATA[Learn how Alfresco delivers more than just cost savings and productivity boosts. Our white paper reveals benefits you may not have thought of when it comes to open source document management. Check it out now!]]></description>
				<content:encoded><![CDATA[<p><a href="http://bluefishgroup.wpengine.com/wp-content/uploads/2012/09/5_Unexpected_Benefits_Open_Source.png"><img class="alignleft  wp-image-720" style="margin-left: 5px; margin-right: 5px;" title="5_Unexpected_Benefits_Open_Source" alt="" src="http://bluefishgroup.wpengine.com/wp-content/uploads/2012/09/5_Unexpected_Benefits_Open_Source-150x150.png" width="84" height="84" /></a>Learn how Alfresco delivers more than just cost savings and productivity boosts. Our white paper reveals benefits you may not have thought of when it comes to open source document management.<br />
</p>
<p><a title="5 Unexpected Benefits fo Open Source Document Management" href="http://info.bluefishgroup.com/acton/form/1396/0005:d-0002/1/index.htm" target="_blank">Check it out now!</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2013/white-paper-5-unexpected-benefits-of-open-source-document-management/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Script to Automate Gathering Support Files in Alfresco</title>
		<link>http://www.bluefishgroup.com/2013/script-to-automate-gathering-support-files-in-alfresco/</link>
		<comments>http://www.bluefishgroup.com/2013/script-to-automate-gathering-support-files-in-alfresco/#comments</comments>
		<pubDate>Sun, 27 Jan 2013 17:30:23 +0000</pubDate>
		<dc:creator>Gary Cox</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Alfresco]]></category>
		<category><![CDATA[Alfresco 4.x]]></category>
		<category><![CDATA[automate gathering support files]]></category>
		<category><![CDATA[script to automate gathering support files]]></category>
		<category><![CDATA[support files]]></category>

		<guid isPermaLink="false">http://bluefishgroup.wpengine.com/?p=877</guid>
		<description><![CDATA[During this video, Gary shares a script to automate gathering support files in Alfresco. Check out our example script and keep in mind this is for Alfresco 4.x. Watch now to learn how to automate gathering support files in Alfresco 4.x using this shell script example. You can see more tips and tricks in our [...]]]></description>
				<content:encoded><![CDATA[<p>During this video, Gary shares a script to automate gathering support files in Alfresco. Check out our example script and keep in mind this is for Alfresco 4.x.<br />
<br />
Watch now to learn how to automate gathering support files in Alfresco 4.x using this shell script example.</p>
<p><iframe width="500" height="281" src="http://www.youtube.com/embed/VBCVfhTy6OM?feature=oembed" frameborder="0" allowfullscreen></iframe></p>
<p>
You can see more tips and tricks in our <a href="/resources/videos/">video library</a>!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2013/script-to-automate-gathering-support-files-in-alfresco/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Webinar: Gas Distribution Closing Packets &#8211; A Case Study on Form-based Document Management</title>
		<link>http://www.bluefishgroup.com/2013/gas-distribution-closing-packets-a-case-study-on-form-based-document-management/</link>
		<comments>http://www.bluefishgroup.com/2013/gas-distribution-closing-packets-a-case-study-on-form-based-document-management/#comments</comments>
		<pubDate>Thu, 17 Jan 2013 19:12:46 +0000</pubDate>
		<dc:creator>Lisa Hill</dc:creator>
				<category><![CDATA[Webinars]]></category>
		<category><![CDATA[Alfresco]]></category>
		<category><![CDATA[document management]]></category>
		<category><![CDATA[gas distribution]]></category>
		<category><![CDATA[webinar]]></category>

		<guid isPermaLink="false">http://bluefishgroup.wpengine.com/?p=723</guid>
		<description><![CDATA[When you are in the business of gas distribution, safety is your top priority. To maintain that safety, engineers in the field need immediate access to relevant documentation about the distribution lines they are servicing. See how our client leveraged their investment in Alfresco Share to automatically generate the forms that must be completed for [...]]]></description>
				<content:encoded><![CDATA[<p>When you are in the business of gas distribution, safety is your top priority. To maintain that safety, engineers in the field need immediate access to relevant documentation about the distribution lines they are servicing. See how our client leveraged their investment in Alfresco Share to automatically generate the forms that must be completed for any given job, and then automatically index and file those documents when they are re-ingested into the Alfresco system so they can be reliably retrieved at a moment’s notice.<br />
<br />
With Lisa Hill, Client Services Director &#8211; Blue Fish Development Group<br />
<br />
<a title="Gas Distribution Closing Packets Webinar" href="http://www.alfresco.com/events/webinars/gas-distribution-closing-packets-case-study-form-based-document-management" target="_blank">Watch now!</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2013/gas-distribution-closing-packets-a-case-study-on-form-based-document-management/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Webinar: Capturing e-Signatures with Alfresco 4 and DocuSign</title>
		<link>http://www.bluefishgroup.com/2012/webinar-capturing-e-signatures-with-alfresco-4-and-docusign/</link>
		<comments>http://www.bluefishgroup.com/2012/webinar-capturing-e-signatures-with-alfresco-4-and-docusign/#comments</comments>
		<pubDate>Tue, 11 Dec 2012 19:19:55 +0000</pubDate>
		<dc:creator>Terence McDevitt</dc:creator>
				<category><![CDATA[Webinars]]></category>
		<category><![CDATA[Alfresco]]></category>
		<category><![CDATA[docusign]]></category>
		<category><![CDATA[e-signatures]]></category>
		<category><![CDATA[ecm]]></category>

		<guid isPermaLink="false">http://bluefishgroup.wpengine.com/?p=724</guid>
		<description><![CDATA[Are document signatures a critical part of your business processes? Are you finding yourself using your ECM to store documents digitally only to have to print those documents out to get physical signatures? Find out how Blue Fish has combined the power of Alfresco 4&#8242;s workflow engine with the simplicity of DocuSign&#8217;s API to enable [...]]]></description>
				<content:encoded><![CDATA[<p>Are document signatures a critical part of your business processes? Are you finding yourself using your ECM to store documents digitally only to have to print those documents out to get physical signatures? Find out how Blue Fish has combined the power of Alfresco 4&#8242;s workflow engine with the simplicity of DocuSign&#8217;s API to enable fully electronic signatures as part of a document workflow.<br />
<br />
In this webinar, Blue Fish will discuss the differences between e-signatures and digital signatures, highlight the various use cases in which e-signatures can be used and show a live demonstration of the integration between Alfresco and DocuSign&#8217;s API.<br />
<br />
With Terence McDevitt, Solution Architect for Blue Fish Development Group<br />
<br />
<a title="Capturing e-Signatures with Alfresco 4 and DocuSign" href="http://www.alfresco.com/events/webinars/capturing-e-signatures-alfresco-4-and-docusign" target="_blank">Download now!</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2012/webinar-capturing-e-signatures-with-alfresco-4-and-docusign/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Webinar: Smooth Like Butter— Representing Tabular Data in Alfresco Share</title>
		<link>http://www.bluefishgroup.com/2012/webinar-smooth-like-butter-representing-tabular-data-in-alfresco-share/</link>
		<comments>http://www.bluefishgroup.com/2012/webinar-smooth-like-butter-representing-tabular-data-in-alfresco-share/#comments</comments>
		<pubDate>Tue, 04 Dec 2012 19:23:47 +0000</pubDate>
		<dc:creator>Gary Cox</dc:creator>
				<category><![CDATA[Webinars]]></category>
		<category><![CDATA[Alfresco]]></category>
		<category><![CDATA[alfresco share]]></category>
		<category><![CDATA[JQuery]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[Lucene]]></category>
		<category><![CDATA[tabular data]]></category>

		<guid isPermaLink="false">http://bluefishgroup.wpengine.com/?p=726</guid>
		<description><![CDATA[Join Blue Fish as we discuss a client’s project that required entry of complex nested tabular data. This data also needed to be searchable from Lucene. While Alfresco supports the concept of repeating attributes on properties, there is no out-of-the-box support for correlating these repeating fields to represent tabular data. Additionally, within Share, there is [...]]]></description>
				<content:encoded><![CDATA[<p>Join Blue Fish as we discuss a client’s project that required entry of complex nested tabular data. This data also needed to be searchable from Lucene. While Alfresco supports the concept of repeating attributes on properties, there is no out-of-the-box support for correlating these repeating fields to represent tabular data. Additionally, within Share, there is no out-of-the-box for support for representing tabular data in forms.<br />
<br />
To achieve the client’s goals for the project, Blue Fish had to determine the best way to both store this data and display it to end users, which created challenges in how to model the data, as well as in how to display it to the end users and enable them to rapidly enter the data. See how Blue Fish tackled these challenges using JSON and JQuery and achieved an end result that is smooth, like butter.<br />
<br />
With Gary Cox &#8211; Senior Consultant, Blue Fish Development Group<br />
<br />
<a title="Webinar Representing Tabular Data in Alfresco Share" href="http://www.alfresco.com/events/webinars/smooth-butter-representing-tabular-data-alfresco-share" target="_blank">Download now!</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2012/webinar-smooth-like-butter-representing-tabular-data-in-alfresco-share/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Webinar: Drillinginfo— Enabling Mission Critical Data Entry and Quality Control Processes with Alfresco in the Oil and Gas Industry</title>
		<link>http://www.bluefishgroup.com/2012/webinar-drillinginfo-enabling-mission-critical-data-entry-and-quality-control-processes-with-alfresco-in-the-oil-and-gas-industry/</link>
		<comments>http://www.bluefishgroup.com/2012/webinar-drillinginfo-enabling-mission-critical-data-entry-and-quality-control-processes-with-alfresco-in-the-oil-and-gas-industry/#comments</comments>
		<pubDate>Tue, 16 Oct 2012 19:32:06 +0000</pubDate>
		<dc:creator>Lisa Hill</dc:creator>
				<category><![CDATA[Webinars]]></category>
		<category><![CDATA[alfreso]]></category>
		<category><![CDATA[data entry]]></category>
		<category><![CDATA[drillinginfo]]></category>
		<category><![CDATA[oil and gas]]></category>
		<category><![CDATA[quality control processes]]></category>

		<guid isPermaLink="false">http://bluefishgroup.wpengine.com/?p=729</guid>
		<description><![CDATA[With Joyanne Moul, Data Analyst – Drillinginfo and Lisa Hill, Client Services Director – Blue Fish Development Group Got Data? Drillinginfo Does! Drillinginfo provides deep data-driven expert analysis that equips the oil and gas industry with the information they need to make good decisions on where to explore, finance, and invest in oil and gas. [...]]]></description>
				<content:encoded><![CDATA[<p>With Joyanne Moul, Data Analyst – Drillinginfo and Lisa Hill, Client Services Director – Blue Fish Development Group<br />
<br />
Got Data?  Drillinginfo Does!  Drillinginfo provides deep data-driven expert analysis that equips the oil and gas industry with the information they need to make good decisions on where to explore, finance, and invest in oil and gas.  They are the most complete source of North American and offshore waters oil and gas information – and that means they have A LOT of data.  Having traditionally relied on a home-grown system to store their data, they had reached a critical breaking point where the system was becoming too brittle and expensive to maintain – they needed a better solution.  Learn how Drillinginfo is now leveraging Alfresco as a critical piece in their data platform.<br />
<br />
<a title="DrillingInfo Webinar " href="http://www.alfresco.com/events/webinars/drillinginfo-enabling-mission-critical-data-entry-and-quality-control-processes" target="_blank">Download now!</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2012/webinar-drillinginfo-enabling-mission-critical-data-entry-and-quality-control-processes-with-alfresco-in-the-oil-and-gas-industry/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>White Paper &#8230;</title>
		<link>http://www.bluefishgroup.com/2012/whitepaper/</link>
		<comments>http://www.bluefishgroup.com/2012/whitepaper/#comments</comments>
		<pubDate>Wed, 03 Oct 2012 07:45:49 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[smooth_slider]]></category>

		<guid isPermaLink="false">http://bluefishgroup.wpengine.com/?p=382</guid>
		<description><![CDATA[Learn how Alfresco delivers more than just cost savings and productivity boosts. Our white paper reveals benefits you may not have thought of when it comes to open source document management. Learn more about the benefits of open source document management.]]></description>
				<content:encoded><![CDATA[<p>Learn how Alfresco delivers more than just cost savings and productivity boosts. Our white paper reveals benefits you may not have thought of when it comes to open source document management.</p>
<div class="slide"><a href="http://info.bluefishgroup.com/acton/form/1396/0005:d-0002/1/index.htm"><img alt="" src="wp-content/themes/shades-of-blue/images/icon1.png" />Learn more about the benefits of open source document management.</a></div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2012/whitepaper/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Got Paper?</title>
		<link>http://www.bluefishgroup.com/2012/postfour/</link>
		<comments>http://www.bluefishgroup.com/2012/postfour/#comments</comments>
		<pubDate>Tue, 25 Sep 2012 07:22:42 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[smooth_slider]]></category>

		<guid isPermaLink="false">http://localhost/bluefish/?p=159</guid>
		<description><![CDATA[Got contracts, forms, or data-intense documents? Whether you process hundreds or thousands of paper documents each day, our simple solution will save your people time and increase data quality. Learn more about our Document Indexing Module for Alfresco.]]></description>
				<content:encoded><![CDATA[<p>Got contracts, forms, or data-intense documents? Whether you process hundreds or thousands of paper documents each day, our simple solution will save your people time and increase data quality.</p>
<div class="slide"><a href="/products-services/document-indexing-module-for-alfresco/"><img style="position: relative; top: 4px; left: 2px;" alt="" src="wp-content/themes/shades-of-blue/images/icon1.png" />Learn more about our Document Indexing Module for Alfresco.</a></div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2012/postfour/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New to Alfresco?</title>
		<link>http://www.bluefishgroup.com/2012/postthree/</link>
		<comments>http://www.bluefishgroup.com/2012/postthree/#comments</comments>
		<pubDate>Tue, 25 Sep 2012 07:22:12 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[smooth_slider]]></category>

		<guid isPermaLink="false">http://localhost/bluefish/?p=157</guid>
		<description><![CDATA[Get up and running with Alfresco quickly with a solution tailored to your business’ specific needs, focused on out of the box features and some bells and whistles from Blue Fish&#8217;s tackle box. Learn more about our Alfresco Quick Start.]]></description>
				<content:encoded><![CDATA[<p>Get up and running with Alfresco quickly with a solution tailored to your business’ specific needs, focused on out of the box features and some bells and whistles from Blue Fish&#8217;s tackle box.</p>
<div class="slide"><a href="/products-services/alfresco-quick-start/"><img style="position: relative; top: 4px; left: 2px;" src="wp-content/themes/shades-of-blue/images/icon1.png" alt="" />Learn more about our Alfresco Quick Start.</a></div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2012/postthree/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Migrations Making You Anxious?</title>
		<link>http://www.bluefishgroup.com/2012/products-serviceszero-downtime-migrations/</link>
		<comments>http://www.bluefishgroup.com/2012/products-serviceszero-downtime-migrations/#comments</comments>
		<pubDate>Tue, 25 Sep 2012 07:16:48 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[smooth_slider]]></category>

		<guid isPermaLink="false">http://localhost/bluefish/?p=153</guid>
		<description><![CDATA[Each year, more than 1.5 million wildebeest migrate across Africa to their new home. We can help your documents do the same thing. Learn More about Migration Workbench and Zero Downtime Migrations.]]></description>
				<content:encoded><![CDATA[<p>Each year, more than 1.5 million wildebeest migrate across Africa to their new home. We can help your documents do the same thing.</p>
<div class="slide"><a href="/products-services/migration-workbench/"><img style="position: relative; top: 4px; left: 2px;" src="wp-content/themes/shades-of-blue/images/icon1.png" alt="" />Learn More about Migration Workbench and Zero Downtime Migrations.</a></div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2012/products-serviceszero-downtime-migrations/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dining Alfresco?</title>
		<link>http://www.bluefishgroup.com/2012/resourcesvideos/</link>
		<comments>http://www.bluefishgroup.com/2012/resourcesvideos/#comments</comments>
		<pubDate>Mon, 24 Sep 2012 07:46:18 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[smooth_slider]]></category>

		<guid isPermaLink="false">http://localhost/bluefish/?p=31</guid>
		<description><![CDATA[Upcoming Lunch and Learn dates are being reserved now. While you wait for your table, join us in the lobby for some educational appetizers. Watch some educational videos to whet your appetite.]]></description>
				<content:encoded><![CDATA[<p>Upcoming Lunch and Learn dates are being reserved now. While you wait for your table, join us in the lobby for some educational appetizers.</p>
<div class="slide"><a href="/resources/videos"><img style="position: relative; top: 4px; left: 2px;" alt="" src="wp-content/themes/shades-of-blue/images/icon1.png" />Watch some educational videos to whet your appetite.</a></div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2012/resourcesvideos/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Webinar: Energy Solution— Leading the Industry in Preventing Natural Gas Pipeline Disasters</title>
		<link>http://www.bluefishgroup.com/2012/webinar-energy-solution-leading-the-industry-in-preventing-natural-gas-pipeline-disasters/</link>
		<comments>http://www.bluefishgroup.com/2012/webinar-energy-solution-leading-the-industry-in-preventing-natural-gas-pipeline-disasters/#comments</comments>
		<pubDate>Tue, 28 Aug 2012 19:35:07 +0000</pubDate>
		<dc:creator>Lisa Hill</dc:creator>
				<category><![CDATA[Webinars]]></category>
		<category><![CDATA[Alfresco]]></category>
		<category><![CDATA[energy solution]]></category>
		<category><![CDATA[HR 2845]]></category>
		<category><![CDATA[natural gas pipeline]]></category>

		<guid isPermaLink="false">http://bluefishgroup.wpengine.com/?p=731</guid>
		<description><![CDATA[In 2010, a natural gas pipeline exploded in San Bruno, California. This devastating accident prompted the US Government to put in place heightened regulatory requirements to ensure enhanced safety and environmental protection in pipeline transportation. Amongst other requirements, HR 2845 mandates that energy companies be able to quickly provide supporting documentation regarding any part of [...]]]></description>
				<content:encoded><![CDATA[<p>In 2010, a natural gas pipeline exploded in San Bruno, California. This devastating accident prompted the US Government to put in place heightened regulatory requirements to ensure enhanced safety and environmental protection in pipeline transportation. Amongst other requirements, HR 2845 mandates that energy companies be able to quickly provide supporting documentation regarding any part of a gas line, including all part and build specifications, line pressure test history, and any service or leak repairs. Learn how Blue FIsh Development Group is helping energy providers leverage their investment in Alfresco to not only comply with these regulations, but also enable their engineers to more quickly and efficiently access relevant information while in the field.<br />
<br />
With Lisa Hill, Blue Fish Development Group<br />
<br />
<a title="Webinar Preventing Natural Gas Pipeline Disasters" href="http://www.alfresco.com/events/webinars/bluefish-preventing-natural-gas-pipeline-disasters" target="_blank">Download now!</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2012/webinar-energy-solution-leading-the-industry-in-preventing-natural-gas-pipeline-disasters/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Webinar: Easy Document Indexing in Alfresco</title>
		<link>http://www.bluefishgroup.com/2012/webinar-easy-document-indexing-in-alfresco/</link>
		<comments>http://www.bluefishgroup.com/2012/webinar-easy-document-indexing-in-alfresco/#comments</comments>
		<pubDate>Tue, 03 Apr 2012 21:56:20 +0000</pubDate>
		<dc:creator>Lisa Hill</dc:creator>
				<category><![CDATA[Webinars]]></category>
		<category><![CDATA[Alfresco]]></category>
		<category><![CDATA[document indexing]]></category>
		<category><![CDATA[OCR solutions]]></category>

		<guid isPermaLink="false">http://bluefishgroup.wpengine.com/?p=775</guid>
		<description><![CDATA[Scanning and manually indexing one or two documents a day is no problem, and there are expensive OCR solutions that will handle tens of thousands of documents each a day. But what about those of us stuck in the middle? Indexing hundreds of documents a day can be really tedious and frustrating, not to mention [...]]]></description>
				<content:encoded><![CDATA[<p>Scanning and manually indexing one or two documents a day is no problem, and there are expensive OCR solutions that will handle tens of thousands of documents each a day. But what about those of us stuck in the middle? Indexing hundreds of documents a day can be really tedious and frustrating, not to mention expensive and error prone. Learn how Blue Fish has helped Alfresco users address this common problem with an easy-to-configure solution that makes indexing fast, practically effortless and almost enjoyable.<br />
<br />
Presented by Lisa Hill, Director of Client Services, Blue Fish Development Group<br />
<br />
<a title="Easy Document Indexing in Alfresco Webinar" href="http://www.alfresco.com/events/webinars/easy-document-indexing-alfresco" target="_blank">Watch now!</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2012/webinar-easy-document-indexing-in-alfresco/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Webinar: Keeping Your Sanity— Rapid Development &amp; Deployment Tools</title>
		<link>http://www.bluefishgroup.com/2012/webinar-keeping-your-sanity-rapid-development-deployment-tools/</link>
		<comments>http://www.bluefishgroup.com/2012/webinar-keeping-your-sanity-rapid-development-deployment-tools/#comments</comments>
		<pubDate>Thu, 22 Mar 2012 19:47:23 +0000</pubDate>
		<dc:creator>Gary Cox</dc:creator>
				<category><![CDATA[Webinars]]></category>
		<category><![CDATA[Alfresco]]></category>
		<category><![CDATA[customizations]]></category>
		<category><![CDATA[deployment framework]]></category>
		<category><![CDATA[deployment tools]]></category>
		<category><![CDATA[rapid development]]></category>

		<guid isPermaLink="false">http://bluefishgroup.wpengine.com/?p=733</guid>
		<description><![CDATA[Deploying customizations into an Alfresco installation can be confusing, difficult, or worse –some very experienced developers have been driven insane by the maze of complexity. Join Gary Cox, Senior Consultant at Blue Fish and learn how Blue Fish uses open source technologies and some special sauce to build a deployment framework that reduces development iteration [...]]]></description>
				<content:encoded><![CDATA[<p>Deploying customizations into an Alfresco installation can be confusing, difficult, or worse –some very experienced developers have been driven insane by the maze of complexity. Join Gary Cox, Senior Consultant at Blue Fish and learn how Blue Fish uses open source technologies and some special sauce to build a deployment framework that reduces development iteration times, improves quality and repeatability, and will keep you out of the asylum.<br />
<br />
<a title="Webinar Rapid Development and Deployment Tools" href="http://www.alfresco.com/events/webinars/keeping-your-sanity-rapid-development-deployment-tools" target="_blank">Download now!</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2012/webinar-keeping-your-sanity-rapid-development-deployment-tools/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Blue Fish Hosting Alfresco Lunch and Learns in 9 US Cities</title>
		<link>http://www.bluefishgroup.com/2011/blue-fish-hosting-alfresco-lunch-and-learns-in-9-us-cities/</link>
		<comments>http://www.bluefishgroup.com/2011/blue-fish-hosting-alfresco-lunch-and-learns-in-9-us-cities/#comments</comments>
		<pubDate>Sun, 10 Apr 2011 14:52:06 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Alfresco]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=454</guid>
		<description><![CDATA[Once a quarter, I spend a few weeks traveling around the country spreading the word about Alfresco by hosting a series of educational Lunch and Learns. This is one of my favorite parts of my job, because I get to meet new people, learn a little bit about their businesses, and turn them onto a [...]]]></description>
				<content:encoded><![CDATA[<p>Once a quarter, I spend a few weeks traveling around the country spreading the word about Alfresco by hosting a series of educational Lunch and Learns. This is one of my favorite parts of my job, because I get to meet new people, learn a little bit about their businesses, and turn them onto a product I really believe in.</p>
<p>This time around, I&#8217;ll be focusing on how you can simplify document management, achieve a paperless office, and streamline your business processes. The main topics I’m going to cover are:</p>
<ul>
<li><strong>General Document Management</strong> &#8211; Alfresco works out of the box with your email and office applications, and has some very clever ways to automate routine document processing tasks. I’ve been implementing document management systems for almost 20 years, and I can tell you that it’s the easiest to use system I’ve ever seen for this type of thing.</li>
<li><strong>Scanning and Archiving Paper Documents</strong> – I’ll show you how you can use the scanner or multi-function printer you already have to turn paper files into electronic images.</li>
<li><strong>Workflow and Business Process Automation</strong> – Alfresco can help you automate your business processes with it’s powerful workflow engine. From approving invoices to revising documents to automating complex business rules, I’ll show you the full breadth of Alfresco’s workflow capabilities. </li>
</ul>
<p>I’ve designed a special workflow that really shows off Alfresco’s bells and whistles, and I’ll be showing it for the first time at this lunch and learn. </p>
<p>So if you are curious about what Alfresco does or how it might be able to benefit your organization, now’s your chance to learn more about it. I’ll be giving a full demonstration of the software and answering all your questions.</p>
<p>All events are from 11:30-1:30, and lunch will be provided.</p>
<ul>
<li><strong>Boston, MA</strong> &#8211; Tuesday, April 26</li>
<li><strong>Orlando, FL</strong> &#8211; Wednesday, April 27</li>
<li><strong>Miami, FL</strong> &#8211; Thursday, April 28</li>
<li><strong>Austin, TX</strong> &#8211; Tuesday, May 3</li>
<li><strong>Houston, TX</strong> &#8211; Wednesday, May 4</li>
<li><strong>Dallas, TX</strong> &#8211; Thursday, May 5</li>
<li><strong>San Antonio, TX</strong> &#8211; Tuesday, May 10</li>
<li><strong>Nashville, TN</strong> &#8211; Wednesday, May 11</li>
<li><strong>Phoenix, AZ</strong> &#8211; Thursday, May 12</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2011/blue-fish-hosting-alfresco-lunch-and-learns-in-9-us-cities/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Social Content Management Features I&#8217;d Like to See in Alfresco Share</title>
		<link>http://www.bluefishgroup.com/2011/social-content-management-features-id-like-to-see-in-alfresco-share/</link>
		<comments>http://www.bluefishgroup.com/2011/social-content-management-features-id-like-to-see-in-alfresco-share/#comments</comments>
		<pubDate>Mon, 21 Mar 2011 13:48:46 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=453</guid>
		<description><![CDATA[Over the past few months, I&#8217;ve heard John Newton (Alfresco founder and CTO) and Todd Barr (Alfresco CMO) speak on a new direction for Alfresco. They are ushering in an era of Social Content Management. Social Content Management is a term coined by Gartner Group, and adopted by Alfresco. It&#8217;s a brand new concept, and [...]]]></description>
				<content:encoded><![CDATA[<p>Over the past few months, I&#8217;ve heard John Newton (Alfresco founder and CTO) and Todd Barr (Alfresco CMO) speak on a new direction for Alfresco. They are ushering in an era of Social Content Management. </p>
<p>Social Content Management is a term coined by Gartner Group, and adopted by Alfresco. It&#8217;s a brand new concept, and the industry hasn&#8217;t yet settled on a standard definition. Alfresco uses it to mean managing the content created by social software. That&#8217;s a platform-oriented view, and it makes sense coming from a platform vendor like Alfresco.</p>
<p>But when I think about Social Content Management, I think about the user. Folks who know me well know I&#8217;m always thinking about the user. I&#8217;m constantly asking questions like &#8220;what are the users trying to accomplish when they use this application?&#8221; or &#8220;what&#8217;s the best user experience to help them achieve their goals?&#8221; At heart, I&#8217;m much more of an applications guy than a platform guy.</p>
<p>So I got to thinking about some of the social networking applications I use regularly, and wondering how we could apply those concepts and features to the realm of document management and collaboration. What I came up with is a list of features I&#8217;d like to see added to Alfresco that I think would make it more social and improve users&#8217; ability to collaborate. To me, that&#8217;s what Social Content Management should be.</p>
<h3>Following Users in Alfresco (Inspired by Facebook)</h3>
<p>At the heart of any social network are our friends – the people we are connected to. We follow them to find out what&#8217;s going on in their personal lives. </p>
<p>But in a business setting, it&#8217;s a bit different. We don&#8217;t want to follow our colleagues&#8217; personal lives; we want to follow their business lives. </p>
<p>You may want to know when a team member has completed the report he was working on. Or a manager might want to keep tabs on what her employees are doing. There are subject matter experts that you would follow to learn more about your company&#8217;s products. People in Sales might want to see what&#8217;s cooking over in Marketing, and vice-versa. </p>
<p>The first feature I want to see is the ability to <b>follow my colleagues in Alfresco</b>. The documents they produce, the discussions they participate in, the comments they make on other people&#8217;s documents – this is the information I want to see when I follow someone&#8217;s business life, and all of this information is stored in Alfresco. </p>
<p>To make it easier to maintain, I want to be able to <b>follow groups as well as users</b> so that I don&#8217;t have to constantly be managing my &#8220;friend&#8221; list as people join and leave the company or move into different departments.</p>
<p>Kicking it up a notch, I also I also want to be able to <strong>follow (or subscribe to) a document</strong>, folder, discussion thread, site, etc.  I want Alfresco to notify me when someone edits a document I&#8217;m following or adds a document to a folder I&#8217;m following.</p>
<p>To make this concept work, I&#8217;ll need an <strong>activity feed that&#8217;s personalized for me</strong> based on the users and groups and documents and folders I&#8217;m following. And since Alfresco added status updates in 3.4, it should include status updates for the users I follow. </p>
<p>To keep my activity feed from getting out of hand, I should be able to fine-tune the types of activities that appear in my feed (see below), and to keep the database from growing out of control, administrators should be able to adjust how long feed items are kept before they are deleted.</p>
<h3>Configurable Activity Feed Dashlet (Inspired by TweetDeck)</h3>
<p>I&#8217;d like to see a <strong>configurable activity feed dashlet</strong>, so that I can filter out activity types I&#8217;m not interested in. This way, I could add the dashlet to my dashboard multiple times with different settings. Maybe I would have one dashlet showing me the activities that are related to documents I&#8217;ve created, another one that shows activities related to users I follow, and a third that is showing subjects I&#8217;m interested in (see below).</p>
<p>The inspiration for this idea comes from <a href="http://www.tweetdeck.com">TweetDeck</a>, the Twitter client I use on my Macintosh. Using TweetDeck, I&#8217;ve created multiple Twitter feeds that let me watch certain subjects or groups of users, and it&#8217;s a thousand times easier for me to make sense of the zillion tweets that zoom past me everyday. I&#8217;ve got some feeds that I watch closely and others that I&#8217;m more casual about.</p>
<p><img height="373" width="560" class="pad-top pad-bottom bordered" src="/images/blog/tweetdeck.png"/></p>
<p>In large sites, Alfresco&#8217;s current activity feed can contains way too much information, so being able to filter out the activities that aren&#8217;t interesting to me will help me cut through the noise created by a zillion activities.</p>
<h3>Email Digests (Inspired by LinkedIn)</h3>
<p>Activity feeds are great for users that spend a lot of time in Alfresco, since they see their feed every time they look at their dashboard. Users that have embraced Facebook in their personal lives are comfortable scanning a feed to stay on top of things. </p>
<p>But the activity feed isn&#8217;t going to work for everyone. Some users don&#8217;t spend much time in Alfresco, and others will be resistant to constantly checking a giant activity feed. Many of these users still live in an email-oriented world, so for them, I want<strong> email digests that recap their activity feeds</strong> or notify them when documents they are following have been modified. This is similar to what I get from LinkedIn, a social networking site that I don&#8217;t visit very often. LinkedIn sends me emails from time to time that keep me updated and let me easily re-engage.</p>
<p>If I had my way, the <strong>email settings would be configured as part of the Activity Feed dashlet</strong>. This way, I could elect to have some of my feeds email me a daily digest and other feeds email me in real-time when the activity happens. </p>
<p>According to my friends at Alfresco, a basic version of this feature is coming in the next release or two, but it will likely only be a daily digest of a single global feed.</p>
<h3>Include Users and Subjects in Comments (Inspired by Twitter)</h3>
<p>The current version of Alfresco lets users comment on documents, folders, blog entries, and links. This is nice, but there are a couple of improvements I&#8217;d like to see.</p>
<p>First, the way that the comment is displayed could be improved. Today, when a user comments on a document, a message is added to the activity feed saying, &#8220;[User] commented on [Document] in site [Site].&#8221; </p>
<p><img height="54" width="550" class="center pad-top pad-bottom bordered" src="/images/blog/share-comment.png"/></p>
<p>I have to click the link to view the document details page so that I can see the comment. I don&#8217;t like this, because it takes a while to load the document details page, and that just wastes time. Also, it breaks my train of thought. The activity feed is great for quickly staying up to date on what&#8217;s happening in Alfresco. But when I click a link in the feed, I&#8217;m taken out of that context to an entirely different page, and when I return to the dashboard, I struggle to find where I was in the feed. </p>
<p>So, the next enhancement I want to see is for the <strong>text of the comment to be included in my activity feed</strong>. </p>
<p>I also want to be able to <strong>direct my comments to specific users</strong>, similar to how Twitter works. I want to be able to include @username in a comment and have the comment be highlighted in that user&#8217;s feed. This would make the discussion around documents much richer, since I could say something like &#8220;I think this report needs more detail. @johndoe, what do you think?&#8221; This tells John Doe that I&#8217;m specifically looking for a response from him.</p>
<p>This notation, used widely on Twitter, will be easy for users to pick up, and if we had configurable dashboards, I&#8217;d create a feed just of the comments that referenced my user name. I&#8217;d set this feed up to email me in real time as the comments were created, so that I could respond quickly.</p>
<p>Building on the idea of using Twitter syntax, I also want to <strong>use hashtag notation in Alfresco comments</strong>. For the uninitiated, hashtags (placing ‘#&#8217; in front of a short word or phrase) is a simple way of tagging a tweet so that others interested in that subject will see it. For example, #alfresco is used on Twitter to indicate that the tweet is about Alfresco, and I have a search set up on Twitter that shows me all the tweets tagged with #alfresco, whether I follow that user or not.</p>
<p><img height="626" width="435" class="center pad-top pad-bottom bordered" src="/images/blog/hashtag.png"/></p>
<p>Allowing hashtags in Alfresco comments would let users tie their comments to a particular project or subject, and other users could search for the hashtag or create a feed of comments related to that hashtag. It would provide another dimension to staying on top of what&#8217;s going on, and would be particularly useful in a large site with lots of users and lots of comments.</p>
<p>What social features do you want to see in Alfresco? Continue the conversation in the comments.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2011/social-content-management-features-id-like-to-see-in-alfresco-share/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Preventing Accidental Access By External Users in Alfresco</title>
		<link>http://www.bluefishgroup.com/2011/preventing-accidental-access-by-external-users-in-alfresco/</link>
		<comments>http://www.bluefishgroup.com/2011/preventing-accidental-access-by-external-users-in-alfresco/#comments</comments>
		<pubDate>Sat, 19 Mar 2011 00:13:00 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=452</guid>
		<description><![CDATA[Imagine that you&#8217;ve set up Alfresco Share as an Intranet within your company, and you&#8217;ve created a site for each department. Every site probably has a small number of managers that invite users, maintain the dashboard, and generally keep the information on the site all nice and tidy. Let&#8217;s say that you also have some [...]]]></description>
				<content:encoded><![CDATA[<p>Imagine that you&#8217;ve set up <a href="http://www2.alfresco.com/l/1234/2010-07-01/I340F">Alfresco Share as an Intranet</a> within your company, and you&#8217;ve created a site for each department. Every site probably has a small number of managers that invite users, maintain the dashboard, and generally keep the information on the site all nice and tidy.</p>
<p>Let&#8217;s say that you also have some sites that you use to collaborate with external customers, partners, or vendors. You&#8217;ve opened up a hole in your firewall so that these external users can access Alfresco Share, and you&#8217;ve been careful to invite those users only to the specific sites that they should have access to.</p>
<p>You may think everything is secure, but no matter how careful you are, when you are letting external users into your Alfresco system, it&#8217;s possible for your internal users to accidentally share sensitive confidential information with those external users. </p>
<p>Here&#8217;s how it can happen.</p>
<h4>1) Creating Public Sites</h4>
<p>When you create a new site in Share, the default visibility is Public, which means that every user in the repository can participate in the site as a consumer, even if they haven&#8217;t officially joined the site. </p>
<p>Documents in public sites are easily returned in search results, and external users can download them and read them without your knowledge. Public sites are a bad idea if you have any external users in your system.</p>
<h4>2) Sharing Documents with Everyone</h4>
<p>Users in Share have the ability to change permissions on documents they create. They can share the document with other users, other groups, or with a special group called &#8220;EVERYONE&#8221;. </p>
<p>It&#8217;s not uncommon for a user to share a document with EVERYONE, assuming that it means everyone in the company, and not realizing that it includes every user in the repository. Most casual users don&#8217;t even realize that the system is being accessed by external users. But when a document is shared with EVERYONE, it&#8217;s available to both internal and external users, and this can allow sensitive information to fall into the wrong hands. </p>
<h4>3) Inviting External Users to Internal Sites</h4>
<p>Managers of sites have permission to invite other users to join their site. They can invite users that already exist in the repository, or they can invite external users that don&#8217;t yet have a user id. Alfresco Share makes it really simple to invite external users, and this can be a problem for some companies. </p>
<p>Let&#8217;s say a site manager invites an external user, but the user does not yet have an login ID for Alfresco. No problem – Alfresco will automatically create a user account, give that account access to the site, and send the user an email with their username, password, and a link to join the site. </p>
<p>While this behavior might be just what you want for an external community site, most IT departments would be horrified to learn that random Alfresco users can give strangers access to the corporate document repository without anyone knowing about it. To make matters worse, the current site manager can give the external user manager-level access, and now the external user can invite even more external users. </p>
<h4>4) Putting External Users in Internal Groups</h4>
<p>Like most enterprise applications, Alfresco has the ability to create groups of users that make managing permissions much easier. In many companies, documents are shared with groups of users, rather than individuals. You might want to give the Marketing group access to the sales team&#8217;s documents, for example. </p>
<p>Lets say that several months later, the marketing team brings on a contractor from an external advertising agency. It only makes sense to put that contractor in the Marketing group so she can get access to the marketing documents. But it&#8217;s often the case that the left hand doesn&#8217;t remember what the right hand has done, and unbeknownst to everyone, this external contractor now has access to all the proposals and sensitive sales documents that you probably wouldn&#8217;t want her to see.</p>
<h3>The Blue Fish Solution</h3>
<p>The way we&#8217;ve solved this problem for our clients is to introduce the concept of external users, external groups, and public folders. In our solution, we&#8217;ve written a job that executes every 30 seconds, identifies external users, and restricts them to accessing only those documents under a public folder.  The nice thing about this approach is that it doesn&#8217;t require any customizations to Share or any serious modifications to the Alfresco server. </p>
<p><b>Here&#8217;s how it works.</b></p>
<p>When our job runs, it identifies all the external users. Any user without a company email address is considered an external user.
<div class="callout">
<p><b>Note: </b>Sometimes, you&#8217;ll have an external contractor or a board member that you trust the same as your internal users, so we&#8217;ve created a group called &#8220;Trusted External Users&#8221;. Add someone with an external email address to this group, and we&#8217;ll treat them like an internal user.</p>
</div>
<p>The first thing that the job does is to make sure that no external users are members of your internal groups. This prevents problem #4 above. We consider most groups in Alfresco to be internal groups, so if we find an external user in an Alfresco group, we will remove that user from the group.</p>
<div class="callout">
<p><b>Note: </b>You may want to group your external users together, for example, into a Customers group or an External Contractors group, so we have a way to designate a group as an external group. It&#8217;s OK for external users to be in external groups.</p>
</div>
<p>Our job then finds any sites we haven&#8217;t seen before. If we encounter a new site, we create a Public folder in that site and set up a new site role called External User. This role appears in all the normal Share dialogs, so you can invite users to your site and give them the External User role. The External User role has no access to any documents except those in the Public folder. </p>
<p>Our job then starts to examine every existing site, looking at the site roles. If we find an external user with a standard site role (Consumer, Collaborator, Contributor, or Manager), we will remove the external user from that role and assign them the External User role. This solves problem #3 above.</p>
<p>The last thing our job does is to look at all the existing documents and folders. If we find that an external user has access to a document or folder outside of the Public folder, we remove that user from the permissions. So even if you explicitly grant an external user access to an internal document, our job will revoke that access 30 seconds later. If an internal user wants to share something with an external user, she has to move it or copy it into the Public folder.</p>
<p>If our job sees any documents or folders that give access to EVERYONE, we revoke that access since it would be visible to external users. In our system, you can&#8217;t give a document access to EVERYONE. This solves problem #1 and problem #2 above.</p>
<p>Whenever our job does takes some action, it emails the Alfresco administrators so they are aware of what&#8217;s going on.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2011/preventing-accidental-access-by-external-users-in-alfresco/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Report: State of Client-Side Web Development</title>
		<link>http://www.bluefishgroup.com/2011/report-state-of-client-side-web-development/</link>
		<comments>http://www.bluefishgroup.com/2011/report-state-of-client-side-web-development/#comments</comments>
		<pubDate>Thu, 17 Feb 2011 15:53:31 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=451</guid>
		<description><![CDATA[Every once in a while, Alex Bilstein, our user interface design guru, writes up an internal report to keep the rest of the Blue Fish team up to speed on the rapid advancements that are taking place in the world of web development, particularly as it relates to front-end development in the web browser tier. [...]]]></description>
				<content:encoded><![CDATA[<p><a href="/article-assets/pdf/BlueFishClientSideReportJan2011.pdf"><img height="257" width="200" class="left pad-right pad-bottom bordered" src="/images/blog/client-side-report.png"/></a></p>
<p>Every once in a while, Alex Bilstein, our user interface design guru, writes up an internal report to keep the rest of the Blue Fish team up to speed on the rapid advancements that are taking place in the world of web development, particularly as it relates to front-end development in the web browser tier.</p>
<p>We thought it might be helpful to others out there, so we&#8217;re sharing it outside of Blue Fish for the first time. Enjoy!</p>
<p>Download Alex&#8217;s <a href="/article-assets/pdf/BlueFishClientSideReportJan2011.pdf">Client Side Report: January 2011</a> (pdf).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2011/report-state-of-client-side-web-development/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Webinar: Painless Document Scanning and Indexing with Alfresco</title>
		<link>http://www.bluefishgroup.com/2011/webinar-recording-painless-document-scanning-and-indexing-with-alfresco/</link>
		<comments>http://www.bluefishgroup.com/2011/webinar-recording-painless-document-scanning-and-indexing-with-alfresco/#comments</comments>
		<pubDate>Wed, 16 Feb 2011 19:59:46 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Webinars]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=450</guid>
		<description><![CDATA[If you missed my recent webinar on an easy way to scan documents into Alfresco, there&#8217;s a recording available. I also uploaded the slides onto SlideShare, but I recommend you watch the recording for the audio and to see the solution in action. Watch Painless Document Scanning and Indexing with Alfresco. Painless Document Scanning and [...]]]></description>
				<content:encoded><![CDATA[<p>If you missed my recent webinar on an easy way to scan documents into Alfresco, there&#8217;s a <a href="http://www2.alfresco.com/l/1234/2011-02-15/P6CJN">recording</a> available.  I also uploaded the slides onto SlideShare, but I recommend you watch the recording for the audio and to see the solution in action.</p>
<p>Watch <a href="http://www2.alfresco.com/l/1234/2011-02-15/P6CJN">Painless Document Scanning and Indexing with Alfresco</a>.</p>
<p  align="center">
<div style="width:425px" id="__ss_6953080"><strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/BlueFishTX/painless-document-scanning-and-indexing-with-alfresco" title="Painless Document Scanning and Indexing with Alfresco">Painless Document Scanning and Indexing with Alfresco</a></strong><object id="__sse6953080" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=painlessdocumentscanningwithalfrescov2-print-110216194006-phpapp02&#038;stripped_title=painless-document-scanning-and-indexing-with-alfresco&#038;userName=BlueFishTX" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed name="__sse6953080" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=painlessdocumentscanningwithalfrescov2-print-110216194006-phpapp02&#038;stripped_title=painless-document-scanning-and-indexing-with-alfresco&#038;userName=BlueFishTX" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object></div></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2011/webinar-recording-painless-document-scanning-and-indexing-with-alfresco/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New Article: Where to Go to Learn About Alfresco</title>
		<link>http://www.bluefishgroup.com/2011/new-article-where-to-go-to-learn-about-alfresco/</link>
		<comments>http://www.bluefishgroup.com/2011/new-article-where-to-go-to-learn-about-alfresco/#comments</comments>
		<pubDate>Thu, 03 Feb 2011 19:40:24 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=449</guid>
		<description><![CDATA[Business analysts, solution architects, developers, and system administrators new to Alfresco all face a similar challenge: figuring out where to go to learn something new about Alfresco. There are tons of wiki pages, blogs, articles, code samples, and other resources on the internet that contain valuable information about Alfresco, but wading through it all can [...]]]></description>
				<content:encoded><![CDATA[<p>Business analysts, solution architects, developers, and system administrators new to Alfresco all face a similar challenge: figuring out where to go to learn something new about Alfresco. </p>
<p>There are tons of wiki pages, blogs, articles, code samples, and other resources on the internet that contain valuable information about Alfresco, but wading through it all can be a daunting chore. In fact, there&#8217;s so much information out there, it&#8217;s hard to know where to start.</p>
<p>My colleague, Nicki DuBose, has written the article I&#8217;ve been waiting for! It&#8217;s a list of best places to go to learn about Alfresco. Nicki and the rest of the Blue Fish team picked out their most helpful articles, web casts, blog posts, wiki pages and compiled them into the ultimate Alfresco resource index on the internet.</p>
<p>Check out <a href="http://www.bluefishgroup.com/library/2011/where-to-go-to-learn-about-alfresco/">Where to Go to Learn About Alfresco</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2011/new-article-where-to-go-to-learn-about-alfresco/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Where to Go to Learn About Alfresco</title>
		<link>http://www.bluefishgroup.com/2011/where-to-go-to-learn-about-alfresco/</link>
		<comments>http://www.bluefishgroup.com/2011/where-to-go-to-learn-about-alfresco/#comments</comments>
		<pubDate>Wed, 02 Feb 2011 12:00:00 +0000</pubDate>
		<dc:creator>Nicki DuBose</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Custom ECM Solutions]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=448</guid>
		<description><![CDATA[Getting Started: How Alfresco Works Terminology Guide &#8211; Skim the Alfresco terminology guide before diving into details of the product. Aflresco Documentation Resource Center &#8211; These &#8220;Getting Started Tutorials&#8221; are great for first-time Alfresco users: &#8220;Alfresco Explorer Document Management&#8221; and &#8220;Getting Started with Alfresco Share Collaboration&#8221;. This site is organized like online help, so navigate [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Getting Started: How Alfresco Works</a><br />
    </h3>
<ul>
<li>
            <a target="_blank" href="http://wiki.alfresco.com/wiki/Terminology_Guide">Terminology Guide</a> &#8211; Skim the Alfresco terminology guide before diving into details of the product.</li>
<li>
            <a target="_blank" href="http://www.alfresco.com/help/34/community/all/">Aflresco Documentation Resource Center</a> &#8211; These &#8220;Getting Started Tutorials&#8221; are great for first-time Alfresco users: &#8220;Alfresco Explorer Document Management&#8221; and &#8220;Getting Started with Alfresco Share Collaboration&#8221;. This site is organized like online help, so navigate the tree on the left to find these tutorials.</li>
<li>
            <a target="_blank" href="http://www2.alfresco.com/l/1234/2010-06-22/I01E7">Alfresco in an Hour</a> &#8211; This webcast will show you many of the features available in Alfresco. </li>
<li>
            <a target="_blank" href="http://blogs.alfresco.com/wp/webcasts/2008/05/replacing-your-shared-drive-with-alfresco/">Replacing your Shared Drive with Alfresco</a> &#8211; This webcast walks you through the &#8220;new to Enterprise Content Management&#8221; scenario.  Take a look if you are new to ECM.</li>
<li>
            <a target="_blank" href="http://www.alfresco.com/community/resources/books/professional-alfresco/">BOOK: Professional Alfresco: Practical Solutions for Enterprise Content Management</a> &#8211; Many will find the first 5-8 chapters useful in understanding the Alfresco landscape.</li>
<li>
            <a target="_blank" href="http://www.alfresco.com/try/">Try Alfresco for Yourself</a> &#8211; This is the best way to learn about how Alfresco works is to play with it.</p>
<ul>
<li>The <a target="_blank" href="http://www.alfresco.com/products/trials/cloud/index.jsp?ct_id=23fbe27a">Cloud Trial</a> is a simple way to take a look at Alfresco Share without installing the product.</li>
<li>You can <a target="_blank" href="http://wiki.alfresco.com/wiki/Download_Community_Edition">Download Alfresco&#8217;s Community Edition</a> free of charge and install it on your own server.</li>
<li>You can <a target="_blank" href="http://www.alfresco.com/products/ecm/enttrial/?product_module=DM">try the Enterprise edition of Alfresco</a> free for 30 days.</li>
</ul>
</li>
</ul>
<h3>
        <a name="head2" class="section">Administering and Configuring Alfresco</a><br />
    </h3>
<ul>
<li>
            <a target="_blank" href="http://wiki.alfresco.com/wiki/Data_Dictionary_Guide">Data Dictionary</a> &#8211; To understand the existing object model, you should review the existing Alfresco Data Dictionary.  This link also gives you a step-by-step guide to defining a new model definition with new content types, aspects, and associations. </li>
<li>
            <a target="_blank" href="http://www.alfresco.com/community/resources/books/professional-alfresco/">BOOK: Professional Alfresco: Practical Solutions for Enterprise Content Management</a> &#8211; Chapters 14-18 will guide you through many of the most common customizations. </li>
<li>
            <a target="_blank" href="http://tinyurl.com/49b4pqp">Administering an Alfresco ECM Production Environment</a> &#8211; In addition to information about installing and administering Alfresco, this document contains a big section on configuration that is worth reviewing.  (Available only with an enterprise license.)</li>
<li>
            <a target="_blank" href="http://www.alfresco.com/community/resources/documentation/">Alfresco Documentation for Community Edition</a> &#8211; Installation and configuration guides for the Alfresco Community Edition.</li>
<li>
            <a target="_blank" href="http://wiki.alfresco.com/">Alfresco Wiki</a> &#8211; The Alfresco Wiki is full of great information, but it can be hard to know where to start. The content on the Wiki is always in flux, so pay close attention to the version/release information in your quest for knowledge.</li>
</ul>
<h3>
        <a name="head3" class="section">Alfresco Development and Customizations</a><br />
    </h3>
<ul>
<li>
            <a target="_blank" href="http://www.alfresco.com/community/resources/books/professional-alfresco/">BOOK: Professional Alfresco: Practical Solutions for Enterprise Content Management</a> &#8211; This book is useful for eveything from understanding the Alfresco landscape to implementing your own customizations.</li>
<li>
            <a target="_blank" href="https://www.packtpub.com/alfresco-developer-guide/book">BOOK: Alfresco Developer Guide</a> &#8211; This book is full of step-by-step instructions on how to implement many of the most common configurations and customizations.  The book will help you do everything from setting up your development environment to packaging and deploying your newly developed customizations.</li>
<li>
            <a target="_blank" href="http://forums.alfresco.com/en/">Alfresco Forums</a> &#8211; A decent, free resource for getting your questions answered.  If you are browsing the forums, in search of a particular roadblock or issue, pay particular attention to the date on the forum threads.  Alfresco has undergone many changes in the years since it was created, so some of the information on both the forums and the Alfresco Wiki may be deprecated or obsolete in the most recent releases.</li>
<li>
            <a target="_blank" href="http://issues.alfresco.com/jira/secure/Dashboard.jspa">Alfresco Issues</a> &#8211; Search for existing issues in Alfresco or add new ones.</li>
<li>
            <a target="_blank" href="http://www.alfresco.com/community/resources/tools/">Alfresco Developer Tools</a> &#8211; The developer tools is a sample code archive. Make sure the code is still applicable to your Alfresco release.</li>
<li>
            <a target="_blank" href="http://www.alfresco.com/help/33/enterprise/api/">Alfresco API Reference</a> &#8211; The API reference is a great resource when you&#8217;re writing custom Web Scripts.</li>
</ul>
<h3>
        <a name="head4" class="section">Keeping Up (Blogs and Tweets)</a><br />
    </h3>
<ul>
<li>
            <a target="_blank" href="http://ecmarchitect.com/">ECM Architect</a> &#8211; Jeff Pott&#8217;s blog is a great way to keep up with some of the changes in Alfresco and Enterprise Content Management.  </li>
<li>
            <a target="_blank" href="http://blogs.alfresco.com/wp/pmonks/">Peter Monks: Alfresco from the trenches</a> &#8211; As head of the Alfresco North American consulting group, Peter Monks blogs about everything ECM. </li>
<li>
            <a target="_blank" href="http://blogs.alfresco.com/planet/">Alfresco Blogs</a> &#8211; A listing of lots of other Alfresco Blogs on the web</li>
<li>If you use twitter, here&#8217;s what to follow:
<ul>
<li>
                    <a target="_blank" href="http://twitter.com/mikeytrafton">@mikeytrafton</a> &#8211; Blue Fish founder and Chief Architect &#8211; retweets the most interesting Alfresco tweets from around the tweetosphere</li>
<li>
                    <a target="_blank" href="http://twitter.com/Alfresco">@Alfresco</a> &#8211; Alfresco&#8217;s company twitter account, posts Alfresco related news and retweets most Alfresco employees</li>
<li>
                    <a target="_blank" href="http://twitter.com/pmonks">@pmonks</a> &#8211; Alfresco consulting guru</li>
<li>
                    <a target="_blank" href="http://twitter.com/johnnewton">@johnnewton</a> &#8211; Alfresco&#8217;s co-Founder and CTO</li>
<li>
                    <a target="_blank" href="http://twitter.com/#search?q=%23Alfresco">#Alfresco</a> &#8211; tweets about Alfresco from the entire Alfresco community</li>
</ul>
</li>
</ul>
<h3>
        <a name="head5" class="section">General Resources</a><br />
    </h3>
<h4>Books</h4>
<ul>
<li>
            <a target="_blank" href="http://www.alfresco.com/community/resources/books/professional-alfresco/">BOOK: Professional Alfresco: Practical Solutions for Enterprise Content Management</a> &#8211; Written by Alfresco CTO and engineering staff</li>
<li>
            <a target="_blank" href="https://www.packtpub.com/alfresco-developer-guide/book">BOOK: Alfresco Developer Guide</a> &#8211; Jeff Potts&#8217; Book</li>
<li>
            <a target="_blank" href="https://www.packtpub.com/alfresco-3-web-services-building-applications-using-Webscripts-and-cmis/book">BOOK: Alfresco 3 Web Services</a>
        </li>
<li>
            <a target="_blank" href="https://www.packtpub.com/alfresco-3-enterprise-content-management-implementation/book">BOOK: Alfresco 3 Enterprise Content Management Implementation</a>
        </li>
</ul>
<h4>Downloads</h4>
<ul>
<li>
            <a target="_blank" href="http://wiki.alfresco.com/wiki/Download_Community_Edition">Community Edition</a> &#8211; The open-source aspect of Alfresco means it is free to download, customize and even use in a production environment.</li>
<li>
            <a target="_blank" href="http://tinyurl.com/4dxv2g6">Enterprise Edition</a> &#8211; The Alfresco 3 Enterpise Edition is available on a per CPU license basis.</li>
</ul>
<h4>Websites</h4>
<ul>
<li>
            <a target="_blank" href="http://www.alfresco.com">Alfresco.com</a>
        </li>
<li>
            <a target="_blank" href="http://www.alfresco.com/help/34/community/all/">Aflresco Documentation Resource Center</a>
        </li>
<li>
            <a target="_blank" href="http://forge.alfresco.com/">Aflresco Forge Community</a>
        </li>
<li>
            <a target="_blank" href="http://forums.alfresco.com/en/">Alfresco Forums</a>
        </li>
<li>
            <a target="_blank" href="https://network.alfresco.com/">Alfresco Network (Requires Enterprise License)</a>
        </li>
<li>
            <a target="_blank" href="http://www.slideshare.net/alfresco/slideshows">Alfresco SlideShare</a>
        </li>
<li>
            <a target="_blank" href="http://blogs.alfresco.com/wp/webcasts/">Alfresco Webcasts</a>
        </li>
<li>
            <a target="_blank" href="http://wiki.alfresco.com/">Alfresco Wiki</a>
        </li>
<li>
            <a target="_blank" href="http://www.youtube.com/user/alfresco101">Alfresco Youtube</a>
        </li>
</ul>
<h3>
        <a name="head6" class="section">Technical</a><br />
    </h3>
<h4>Alfresco Technical Resources</h4>
<ul>
<li>
            <a target="_blank" href="http://wiki.alfresco.com/wiki/Web_Scripts">Alfresco Web Scripts</a>
        </li>
<li>
            <a target="_blank" href="http://wiki.alfresco.com/wiki/3.0_Web_Scripts_Framework">Web Scripts Framework</a>
        </li>
<li>
            <a target="_blank" href="http://wiki.alfresco.com/wiki/Spring_Surf">Spring Surf Platform &#8211; Developers Guide</a>
        </li>
<li>
            <a target="_blank" href="http://wiki.alfresco.com/wiki/Main_Page">Alfresco Wiki</a>
        </li>
</ul>
<h4>Code Samples</h4>
<ul>
<li>
            <a target="_blank" href="http://drquyong.com/myblog/?p=25">Dr. Q&#8217;s Workshop &#8211; Hello World Dashlet</a>
        </li>
<li>
            <a target="_blank" href="http://www.bluefishgroup.com/library/2010/painless-alfresco-development-source-code-organization/">Blue Fish &#8211; Alfresco Source Code Organization</a>
        </li>
<li>
            <a href="/article-assets/code/ExampleConfigurableDashletSource.zip">Example Dashlet Source Code</a>
        </li>
</ul>
<h4>Third-Party Resources</h4>
<ul>
<li>
            <a target="_blank" href="http://lucene.apache.org/java/docs/index.html#Apache%20Lucene">Apache Lucene</a>
        </li>
<li>
            <a target="_blank" href="http://freemarker.sourceforge.net/">FreeMarker</a>
        </li>
<li>
            <a target="_blank" href="http://java.sun.com/javaee/javaserverfaces/overview.html">Java Server Faces</a>
        </li>
<li>
            <a target="_blank" href="http://crockford.com/javascript/jsmin.html">JSMin &#8211; The JavaScript Minifier</a>
        </li>
<li>
            <a target="_blank" href="http://www.springsource.org/">Spring</a>
        </li>
<li>
            <a target="_blank" href="http://www.springsource.org/extensions/se-surf">Spring Surf</a>
        </li>
</ul>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2011/where-to-go-to-learn-about-alfresco/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Tweet Round-Up: Alfresco 3.4 Launch</title>
		<link>http://www.bluefishgroup.com/2011/tweet-round-up-alfresco-34-launch/</link>
		<comments>http://www.bluefishgroup.com/2011/tweet-round-up-alfresco-34-launch/#comments</comments>
		<pubDate>Sat, 29 Jan 2011 07:54:52 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=446</guid>
		<description><![CDATA[Here&#8217;s a round-up of the best articles, videos, and blog posts about this week&#8217;s launch of Alfresco Enterprise 3.4.]]></description>
				<content:encoded><![CDATA[<p>Here&#8217;s a round-up of the best articles, videos, and blog posts about this week&#8217;s launch of Alfresco Enterprise 3.4. </p>
<p><script src="http://keepstream.com/mikeytrafton/tweets-about-the-launch-of-alfresco-3-4-.js" type="text/javascript"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2011/tweet-round-up-alfresco-34-launch/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Video: What&#8217;s New in Alfresco 3.4</title>
		<link>http://www.bluefishgroup.com/2011/video-whats-new-in-alfresco-34/</link>
		<comments>http://www.bluefishgroup.com/2011/video-whats-new-in-alfresco-34/#comments</comments>
		<pubDate>Thu, 27 Jan 2011 17:00:34 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=445</guid>
		<description><![CDATA[Interested in what&#8217;s new in the latest version of Alfresco? I recorded a little demo video to show you the most interesting bits.]]></description>
				<content:encoded><![CDATA[<p>Interested in what&#8217;s new in the latest version of Alfresco? I recorded a little demo video to show you the most interesting bits.</></p>
<p><iframe title="YouTube video player" class="youtube-player" type="text/html" width="560" height="345" src="http://www.youtube.com/embed/xlaWScYlBdA?rel=0&amp;hd=1" frameborder="0" allowFullScreen></iframe></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2011/video-whats-new-in-alfresco-34/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Alfresco Lunch and Learns in 6 Cities</title>
		<link>http://www.bluefishgroup.com/2011/alfresco-lunch-and-learns-in-6-cities/</link>
		<comments>http://www.bluefishgroup.com/2011/alfresco-lunch-and-learns-in-6-cities/#comments</comments>
		<pubDate>Wed, 05 Jan 2011 15:38:32 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=444</guid>
		<description><![CDATA[We&#8217;re starting 2011 off with another round of Blue Fish and Alfresco Lunch and Learn events. At this Lunch and Learn, I&#8217;ll be demonstrating some of the great things that Alfresco can do out of the box, and I&#8217;ll be showing off a brand new extension to Alfresco that makes it easy to scan and index paper documents and [...]]]></description>
				<content:encoded><![CDATA[<p>We&#8217;re starting 2011 off with another round of Blue Fish and Alfresco Lunch and Learn events.  At this Lunch and Learn, I&#8217;ll be demonstrating some of the great things that Alfresco can do out of the box, and I&#8217;ll be showing off a brand new extension to Alfresco that makes it easy to scan and index paper documents and manage them in Alfresco.  We&#8217;ve never shown it in public before, so you&#8217;ll be the first to see it.  If you&#8217;ve been considering Alfresco as a solution to scan paper document, you won&#8217;t want to miss this Lunch and Learn.</p>
<p>We’ll be hosting these events in 6 cities across 3 states:</p>
<ul>
<li><strong>Austin, TX</strong> &#8211; Tuesday, January 18 &#8211; <a href="http://www.alfresco.com/about/events/lunch-learns/register/?code=lunchlearn_2010_Q4_AUS">Register</a><br /></span></li>
<li><strong>Houston, TX</strong> &#8211; Wednesday, January 19 &#8211; <a href="http://www.alfresco.com/about/events/lunch-learns/register/?code=lunchlearn_2010_Q4_HOU">Register</a><br /></span></li>
<li><strong>Dallas, TX</strong> &#8211; Thursday, January 20 &#8211; <a href="http://www.alfresco.com/about/events/lunch-learns/register/?code=lunchlearn_2010_Q4_DAL">Register</a><br /></span></li>
<li><strong>Boston, MA</strong> &#8211; Tuesday, January 25 &#8211; <a href="http://www.alfresco.com/about/events/lunch-learns/register/?code=lunchlearn_2010_Q4_BOS">Register</a><br /></span></li>
<li><strong>Orlando, FL</strong> &#8211; Wednesday, January 26 &#8211; <a href="http://www.alfresco.com/about/events/lunch-learns/register/?code=lunchlearn_2010_Q4_ORL">Register</a><br /></span></li>
<li><strong>Miami, FL </strong>- Thursday, January 27- <a href="http://www.alfresco.com/about/events/lunch-learns/register/?code=lunchlearn_2010_Q4_MIA">Register</a></span></li>
</ul>
<p>I&#8217;m really excited to share this information and help you plan your 2011 ECM initiatives.  Space is limited, so please register early to secure your place. I hope to see you there.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2011/alfresco-lunch-and-learns-in-6-cities/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Alfresco Lunch and Learns in October</title>
		<link>http://www.bluefishgroup.com/2010/alfresco-lunch-and-learns-october2010/</link>
		<comments>http://www.bluefishgroup.com/2010/alfresco-lunch-and-learns-october2010/#comments</comments>
		<pubDate>Thu, 16 Sep 2010 20:13:22 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=443</guid>
		<description><![CDATA[Blue Fish and Alfresco are hosting another round of lunch and learns to introduce folks to the benefits of using Alfresco as an Enterprise Content Management platform. If you&#8217;ve been wondering what Alfresco has been up to lately, you might really enjoy this session. We&#8217;re trying to get the word out to as many people [...]]]></description>
				<content:encoded><![CDATA[<p>Blue Fish and Alfresco are hosting another round of lunch and learns to introduce folks to the benefits of using Alfresco as an Enterprise Content Management platform. If you&#8217;ve been wondering what Alfresco has been up to lately, you might really enjoy this session.</p>
<p>We&#8217;re trying to get the word out to as many people as possible, so this time, we’ll be hosting these events in 7 cities across 3 states:</p>
<ul>
<li><b>Houston, TX</b> &#8211; Tuesday, October 5 &#8211; <a href="http://www.alfresco.com/about/events/lunch-learns/register/?code=lunchlearn_2010_Q3_HOU">Register</a></li>
<li><b>Dallas, TX</b> &#8211; Wednesday, October 6 &#8211; <a href="http://www.alfresco.com/about/events/lunch-learns/register/?code=lunchlearn_2010_Q3_DAL">Register</a></li>
<li><b>Austin, TX</b> &#8211; Thursday, October 7 &#8211; <a href="http://www.alfresco.com/about/events/lunch-learns/register/?code=lunchlearn_2010_Q3_AUS">Register</a></li>
<li><b>San Antonio, TX</b> &#8211; Friday, October 8 &#8211; <a href="http://www.alfresco.com/about/events/lunch-learns/register/?code=lunchlearn_2010_Q3_SAN">Register</a></li>
<li><b>Atlanta, GA</b> &#8211; Tuesday, October 12 &#8211; <a href="http://www.alfresco.com/about/events/lunch-learns/register/?code=lunchlearn_2010_Q3_ATL">Register</a></li>
<li><b>Tampa, FL</b> &#8211; Wednesday, October 13 &#8211; <a href="http://www.alfresco.com/about/events/lunch-learns/register/?code=lunchlearn_2010_Q3_TAM">Register</a></li>
<li><b>Jacksonville, FL</b> &#8211; Thursday, October 14 &#8211; <a href="http://www.alfresco.com/about/events/lunch-learns/register/?code=lunchlearn_2010_Q3_JKS">Register</a></li>
</ul>
<p>This round of lunch and learns will be focused on Web Content Management (WCM) and Records Management. I’ll be presenting at each of them, and I&#8217;m hoping to be able to show you some of the cool new WCM features that are coming down the road.</p>
<p>Space is limited, so please <b>register early</b> to secure your place. I hope to see you there.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2010/alfresco-lunch-and-learns-october2010/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New Articles: Using Custom Fonts On Your Web Sites</title>
		<link>http://www.bluefishgroup.com/2010/new-articles-using-custom-fonts-on-your-web-sites/</link>
		<comments>http://www.bluefishgroup.com/2010/new-articles-using-custom-fonts-on-your-web-sites/#comments</comments>
		<pubDate>Tue, 22 Jun 2010 21:28:57 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=439</guid>
		<description><![CDATA[Alex Bilstein is Blue Fish&#8217;s User Interface Designer and Front-End Developer Extraordinaire, and he&#8217;s just written three amazing articles about how to use custom fonts on the web. Custom fonts are all those cool looking fonts that you see on posters, billboards, and other print advertising. Most computers don&#8217;t have these fonts installed, so designers [...]]]></description>
				<content:encoded><![CDATA[<p>Alex Bilstein is Blue Fish&#8217;s User Interface Designer and Front-End Developer Extraordinaire, and he&#8217;s just written three amazing articles about how to use custom fonts on the web.</p>
<p>Custom fonts are all those cool looking fonts that you see on posters, billboards, and other print advertising. Most computers don&#8217;t have these fonts installed, so designers buy them from font &#8220;foundries&#8221; to use in their designs. Web site designers are at a disadvantage, because in order to use a font on a web site, it needs to be installed on the web visitor&#8217;s computer, and most computers have only a handful of standard fonts installed. This is why most web sites use the same two or three fonts over and over again &#8211; those are the fonts that are installed on every computer out there.</p>
<p>Over the years, crafty designers and web developers have been coming up with clever ways for web sites to use custom fonts even if they are not installed on their visitors&#8217; computers. The techniques have evolved over time, and now there are some pretty good ways of doing this. </p>
<p>Alex has written three articles that will get you up to speed on what you need to know to use custom fonts on your web sites.</p>
<ul>
<li><a href="http://www.bluefishgroup.com/library/2010/what-to-know-when-considering-web-fonts/">What to Know When Considering Custom Fonts for Your Web Site</a></li>
<li><a href="http://www.bluefishgroup.com/library/2010/font-face-the-easiest-way-to-use-custom-fonts/">@font-face: The Easiest Way to Use Custom Fonts on Your Web Site</a></li>
<li><a href="http://www.bluefishgroup.com/library/2010/web-font-realities-case-study/">Web Font Realities &#8211; A Case Study in Implementing Custom Fonts on a Modern Web Site</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2010/new-articles-using-custom-fonts-on-your-web-sites/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Web Font Realities &#8211; A Case Study in Implementing Custom Fonts on a Modern Web Site</title>
		<link>http://www.bluefishgroup.com/2010/web-font-realities-case-study/</link>
		<comments>http://www.bluefishgroup.com/2010/web-font-realities-case-study/#comments</comments>
		<pubDate>Tue, 22 Jun 2010 11:00:00 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Web Content Management]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=442</guid>
		<description><![CDATA[Introduction Recent advances in browser technology and font creation tools mean that web fonts can be used today with very good browser support. Unfortunately, web font licensing can complicate the issue. In this article, we&#8217;ll discuss the technical challenges and legal process we followed when implementing web fonts on the Blue Fish Development Group web [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Introduction</a><br />
    </h3>
<p>Recent advances in browser technology and font creation tools mean that web fonts can be used today with very good browser support. Unfortunately, web font licensing can complicate the issue. In this article, we&#8217;ll discuss the technical challenges and legal process we followed when implementing web fonts on the Blue Fish Development Group web site.</p>
<h3>
        <a name="head2" class="section">Web Font LIcensing</a><br />
    </h3>
<p>The Blue Fish corporate identity includes the Trade Gothic font from Linotype GmbH. We&#8217;d like to use that font on our web site for various headers, links, and other callouts in order to reinforce our brand throughout the site. Let&rsquo;s take a look at what an article title looks like with Arial (top) compared to Trade Gothic (bottom):</p>
<div align="center">
        <img src="/article-assets/images/web-fonts-realities/font-styles.png" border="0" alt="Fig. 1: font-faces.png">
<p class="figure">
            <b><br />
              Figure 1:<br />
            </b> A comparison of font faces showing Arial (top) and Trade Gothic Bold Condensed No. 20 (bottom).</p>
</p></div>
<p>That&rsquo;s a pretty striking difference! So, how can we display our preferred font for our article titles? As we described in our &#8220;<a href="/library/2010/font-face-the-easiest-way-to-use-custom-fonts/">@font-face: The Easiest Way to Use Custom Fonts on Your Web Site</a>&#8221; article, implementing @font-face is our recommended best practice for implementing custom fonts on modern web sites. But that doesn&rsquo;t necessarily mean that we could just run off and follow our own best practice &#8211; first we had to find out if Linotype allows web font linking (the general term for using @font-face) as part of their license agreement.</p>
<p>We were in luck &#8211; according to the Linotype web site, they do allow web font linking! Unfortunately, their <a target="_blank" href="http://www.linotype.com/5926/eotfonts.html">web font embedding license page</a> states they only permit the EOT font format, and there is no information on pricing. We had to contact them directly for more information.</p>
<p>After some communication with a Linotype representative, we learned that Trade Gothic can be licensed for EOT web linking, but not TTF, OTF, or WOFF linking due to the lack of encryption in those formats. That&rsquo;s a start, but EOT is only supported by Internet Explorer, which is about 50% of our traffic &#8211; how will we display our font to everyone else?</p>
<p>Fortunately, our Linotype contacts told us that they also allow the use of sIFR and Cufon, even though it isn&rsquo;t explicitly stated on their web site. While we would prefer to use @font-face for all browsers, this is an acceptable method which will allow us to use our preferred font.</p>
<p>With the allowed formats understood, we then needed to purchase a license. Linotype&#8217;s US licensor is Monotype Imaging (fonts.com), and we contacted a customer service representative. The first thing they asked is how we&#8217;ll be using the font. Is it only for displaying text on the web site (requiring an EOT license), or will it be used in an online application that allows users to generate their own text (which requires a <a target="_blank" href="http://www.fonts.com/FontServices/FontEmbedding.htm">Web Server License</a>. In our case, we only need an EOT license.</p>
<p>A sales representative then contacted us with a bit of surprising news &#8211; Monotype had just launched a new hosted web font service. They will continue to offer their traditional web font license but their preferred model is the new hosted service. There will be an initial free beta period with approximately 2,000 fonts available, followed later in the year by a commercial service featuring their entire library of over 7,000 fonts. While we are currently hosting the fonts ourselves, we have decided to purchase their hosted license in the future once it moves out of beta (until then, we&#8217;ll keep using the method described in this article). In both cases the license fee is determined by the number of unique visitors per month and the number of fonts licensed. However, not only is the hosted service cheaper, but it includes a content delivery network which means better performance for end users.</p>
<p>With the licensing issue resolved, we moved on to the technical implementation. In our case, that means using @font-face to serve EOT fonts to Internet Explorer users with a Cufon fallback for all other browsers.</p>
<h3>
        <a name="head3" class="section">Generating the EOT Font</a><br />
    </h3>
<p>Monotype doesn&#8217;t provide EOT files, so we needed to generate those ourself. In order to do that, we used Font Squirrel&#8217;s @font-face generator and our standard desktop OTF font. Here are the settings we used: selected EOT, Add Hinting, Remove Kerning, subset our fonts to Basic Latin (because our site is English only), choose the Mo&#8217; Bulletproofer CSS code, and agreed to the EULA statement. This is what it looked like on the Font Squirrel web site:</p>
<div align="center">
        <img src="/article-assets/images/web-fonts-realities/font-face-generator.png" border="0" alt="Fig. 2: ">
<p class="figure">
            <b><br />
              Figure 2:<br />
            </b> Font Squirrel&#8217;s @font-face Kit Generator</p>
</p></div>
<p>The generator provided us with the following three files:</p>
<ul>
<li>EOT font file</li>
<li>CSS sample file</li>
<li>HTML sample file</li>
</ul>
<p>The resulting EOT file is only 20KB as opposed to the original 29KB OTF. The generated CSS file has two rules, but we only needed the first one for EOT:</p>
<pre>
        <code>
@font-face {
	font-family: 'trade-gothic-bold-condensed';
	src: url('tradegothicltstdbdcn20.eot');
}
</code>
    </pre>
<p>This is the only CSS rule needed to support Internet Explorer, which according to our web site analytics is about 50% of our traffic. We used Cufon to support the other half of our visitors.</p>
<h3>
        <a name="head4" class="section">Generating the Cufon Font</a><br />
    </h3>
<p>As I mentioned earlier, Linotype allows the use of sIFR and Cufon under the EOT license. These are similar technologies, and each has their own advantages. But ultimately we decided to use Cufon due to its use of standards based technologies rather than relying on the Flash plugin. The main advantage this provides is that our fonts will work on Apple&#8217;s iPhone and iPad.</p>
<p>You may have noticed that the Font Squirrel @font-face generator offers Cufon as one of the format options. However, the official Cufon generator sometimes provides better compression, and it also allows domain binding as an extra security measure. Once again using our original OTF Trade Gothic Font, we went to the official Cufon generator and uploaded our font. We chose a name for the font (the same font-family name we are using for EOT), agreed with the EULA, subset the font to Basic Latin, and limited usage to *.bluefishgroup.com. The rest of the options we left as defaults. This is what it looked like on the Cufon web site:</p>
<div align="center">
        <img src="/article-assets/images/web-fonts-realities/cufon-1.png" border="0" alt="Fig. 3: Cufon screenshot">
<p class="figure">
            <b><br />
              Figure 3:<br />
            </b> Cufon font upload and naming</p>
</p></div>
<div align="center">
        <img src="/article-assets/images/web-fonts-realities/cufon-2.png" border="0" alt="Fig. 4: Cufon screenshot">
<p class="figure">
            <b><br />
              Figure 4:<br />
            </b> Cufon font settings</p>
</p></div>
<div align="center">
        <img src="/article-assets/images/web-fonts-realities/cufon-3.png" border="0" alt="Fig. 5: Cufon screenshot">
<p class="figure">
            <b><br />
              Figure 5:<br />
            </b> Cufon security</p>
</p></div>
<p>The resulting Javascript font file is only 16KB. After we had generated the Cufont Javascript font file, we downloaded the minified cufon-yui.js library file as well.</p>
<h3>
        <a name="head5" class="section">Putting it all Together</a><br />
    </h3>
<p>At this point, we had an EOT font file, a Javascript font file, and the Cufon Javascript library file. We needed to upload those three files to our server and include them in our site header. Next, we added the CSS rule above to our existing CSS file.</p>
<p>When Internet Explorer reads this rule, it will download the EOT file and use it on our site. All other browsers will ignore it because they do not support EOT. Ideally, you should place this CSS in a separate style sheet that is only served to Internet Explorer.</p>
<p>Finally, we needed to enable Cufon on our site. We had already completed step 1 and 2 in their usage guide (generating the font and downloading the library). The last thing we had to do was add the Cufon Javascript call to our base Javascript file.</p>
<pre>
        <code>
Cufon.replace('.title');
</code>
    </pre>
<p>This tells Cufon to use the Trade Gothic font for any element on the page with the class &lsquo;.title&rsquo;. You may have noticed there is a step 4 in the Cufon Usage guide &#8211; &lsquo;Making Internet Explorer behave&rsquo;. We don&rsquo;t have to worry about that because we&rsquo;re serving EOT to IE.</p>
<p>We were not quite done yet. The above code will replace all of our &lsquo;.title&rsquo; elements with Cufon elements, but we only want Cufon to target browsers other than IE. So we had to add some conditional compilation to our Javascript to make sure that only non-IE browsers get that code:</p>
<pre>
        <code>
/*@cc_on
    @if (@_jscript == false)
        */initCufon();/*
    @end 
@*/
</code>
    </pre>
<p>I won&#8217;t go into the details here, but conditional compilation is a fully supported IE mechanism to target different versions of the IE JScript engine. This particular snippet calls the Cufon method for all browsers except for IE.</p>
<p>At this point, our web site could serve Trade Gothic article headers to all of our users, but we were not quite ready to go live. Next, we optimized our Javascript (including the Cufon generated Trade Gothic Javascript font) by using Gzip on the server. This can reduce the file size by 25%-50%, which translates to a better user experience.</p>
<p>Finally, we needed to make sure we were using the right font stack. In order to reduce the impact of any flash of unstyled text, we chose a stack with fonts of similar width and kerning. In the case of Trade Gothic Bold Condensed No. 20, we choose the following stack:</p>
<pre>
        <code>
.title {
	font-family: trade-gothic-bold-condensed, "Arial Narrow", Impact, Sans-Serif;
}
</code>
    </pre>
<p>Which results in the following font cascade:</p>
<div align="center">
        <img src="/article-assets/images/web-fonts-realities/font-stack.png" border="0" alt="Fig. 6: Font stack">
<p class="figure">
            <b><br />
              Figure 6:<br />
            </b> Font stack cascade from Trade Gothic to Sans-Serif</p>
</p></div>
<h3>
        <a name="head6" class="section">Conclusion</a><br />
    </h3>
<p>Ideally, we would use @font-face for all browsers. But because of our restricted web font license, a little creative fall back was used. With the help of a little conditional compilation in our Javascript, IE users are served EOT font files using @font-face, and all other browsers are served Cufon fonts.</p>
<p>Hopefully, one day browser vendors, font foundries, and web designers can all agree on a single format and implementation for web typography. Until then, we&rsquo;ll continue to use a combination of techniques to ensure we deliver the best experience possible to all of our users.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2010/web-font-realities-case-study/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>What to Know When Considering Custom Fonts for Your Web Site</title>
		<link>http://www.bluefishgroup.com/2010/what-to-know-when-considering-web-fonts/</link>
		<comments>http://www.bluefishgroup.com/2010/what-to-know-when-considering-web-fonts/#comments</comments>
		<pubDate>Tue, 22 Jun 2010 11:00:00 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Web Content Management]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=440</guid>
		<description><![CDATA[Introduction Web designers want to create beautiful web sites that stand out from the crowd, and in order to do so these designs often use non-standard fonts or typefaces. However, since most computers probably don&#8217;t have these custom fonts installed, they will often display the designer&#8217;s web site with unexpected results. For example, notice the [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Introduction</a><br />
    </h3>
<p>Web designers want to create beautiful web sites that stand out from the crowd, and in order to do so these designs often use non-standard fonts or typefaces. However, since most computers probably don&#8217;t have these custom fonts installed, they will often display the designer&#8217;s web site with unexpected results. For example, notice the typography in the design below:</p>
<div align="center">
        <img src="/article-assets/images/web-fonts-what-to-know/brizk.png" border="0" alt="Fig. 1: Example of the same sight with and without custom fonts">
<p class="figure">
            <b><br />
              Figure 1:<br />
            </b> Web site brizk.com with generic fonts on the left, and custom fonts using @font-face on the right. Notice that not only do the fonts change in visual appearance, but the layout is affected as well.</p>
</p></div>
<p>See the difference? When attempting to use custom typography on the web, designers have typically been left with two options &ndash; creating images that contain the text on the web site, or changing the design to use one of the boring standard fonts that are supported on every computer.</p>
<p>However, recent advances in browser technology and emerging font formats are affording new opportunities for typographic control. Unfortunately, these advances are not without their issues, because different browsers support different font formats, and some font foundries restrict the ways in which their fonts can be used on the web.</p>
<p>This article will help you understand the two most important aspects of using a custom font on your web site:</p>
<ol>
<li>When, why, and how to use the latest web font technologies, and</li>
<li>How to navigate the emerging web font licensing landscape.</li>
</ol>
<h3>
        <a name="head2" class="section">Technical Options for Using Custom Fonts on the Web</a><br />
    </h3>
<p>In the past, most content on the web was static. Designers and developers created their pages locally and then uploaded them to a server. If there was a need for custom typography, the designer would create the text as an image using an application such as Photoshop. Although not ideal (it required a graphic designer to make any text changes), it worked well enough for the committed web team.</p>
<p>However, with the introduction of web content management systems and user generated content, this strategy became difficult at best. No longer could images be manually created to render text with custom fonts, because the graphic designer no longer made all of the updates to the web site.</p>
<p>To address this lack of font flexibility, a number of workaround techniques have been developed that allow custom fonts to be used without creating a separate image for every piece of text. Let&#8217;s take a look at the three of the most common techniques from recent years.</p>
<h4>Dynamic Image Rendering</h4>
<p>There are server side techniques that can be used to convert plain text into image text on the fly. This is essentially the same thing as having a designer create the image text for you, but it is instead done automatically by software. The advantage to this technique is that it is cross browser compatible and works even in very old browser versions as the end result is simply a standard image. However, the images cause pages to render more slowly, and there are often technical implementation challenges. There are <a target="_blank" href="http://facelift.mawhorter.net/learn-more/">third party solutions</a> that will do the processing for you, but in the end you&#8217;re still left with an image that is less desirable in respect to SEO, accessibility, and usability.</p>
<p>Today and even in the near future, rendering text as an image still provides the most control and browser consistency. Graphic design programs like Adobe Photoshop allow a degree of control over kerning, tracking, scaling, and other properties that browsers are simply incapable of via CSS. If it has to be pixel perfect, this is still the only way to go. However, this technique doesn&#8217;t scale very well for user generated content.</p>
<h4>sIFR</h4>
<p>
        <a target="_blank" href="http://novemberborn.net/sifr3">sIFR</a> has probably been the most popular font replacement technique in recent years. It is a Javascript and Flash solution that dynamically replaces your plain text with a Flash object.</p>
<p>Here&#8217;s how it works. You identify headlines or other text where you want to use a custom font by assigning a specific CSS class. After the page renders in a browser, sIFR will parse the page and replace the rendered text with a small flash file that displays that text in your custom font. This usually happens so quickly that the web page visitor doesn&#8217;t even notice.</p>
<p>With sIFR, you can achieve very satisfactory results with a good degree of typographic control. However, it comes with a performance cost, has some limitations in regard to styling via CSS,  is a bit cumbersome to set up, and requires the Flash plugin (which means it won&#8217;t work on the iPhone or iPad). Despite these shortcomings, sIFR is quite popular and offers broad browser support due to the ubiquity of the Flash plugin.</p>
<h4>Cufon</h4>
<p>A relatively recent technique, <a target="_blank" href="http://cufon.shoqolate.com/">Cufon</a> is similar in concept to sIFR but relies on web standards as opposed to a proprietary plugin. Using the appropriate combination of Javascript, Canvas, SVG, and VML, Cufon replaces your plain text with HTML vector elements in your desired font. It works in all modern browsers including mobile devices. The results are quite nice, and the Cufon web site has a generator that creates all the necessary files for you.</p>
<p>The down side of Cufon is that the text is not easily selectable, some common CSS styling is unavailable (I&#8217;m looking at you, text-decoration), and there are some accessibility issues.</p>
<h3>
        <a name="head3" class="section">@font-face</a><br />
    </h3>
<p>@font-face is a CSS rule that allows you to publish fonts on your server and then serve them up to browsers just as you would any other font already installed on the client operating system. This technique is also called font linking, because the CSS links to a font file on your server that is downloaded and used by the browser.</p>
<p>The <a target="_blank" href="http://www.w3.org/TR/css3-fonts/">@font-face CSS rule</a> has been around for over 10 years (although only recently as a web standard), but it has seen little use because it only worked in Internet Explorer. However, recent versions of Firefox, Chrome, Safari, and Opera all support @font-face in one way or another.</p>
<p>While all modern browsers support font linking, they differ in what font formats they support. Fortunately, it is now possible to support virtually all browsers with a couple of font formats and some simple CSS tricks that we will show you later in this article. While there are limitations to the amount of typographic control one has when using @font-face, the benefits far outweigh the limitations.</p>
<p>Let&#8217;s take a look at the different font formats currently in use.</p>
<h4>Embedded Open Type (EOT)</h4>
<p>Embedded Open Type has been around since the late 1990&#8242;s, but because it was difficult to work with and only worked in Internet Explorer, it never gained widespread use. Today, however, EOT files are much easier to create and can be used alongside other formats, so EOT has become much more relevant. While it still only works in IE, EOT is stable, compressed, and because it is encrypted, it is the font linking format favored by most font foundries.</p>
<h4>True Type Fonts (TTF) and Open Type Fonts (OTF)</h4>
<p>True Type Fonts and Open Type Fonts are probably what you have installed on your desktop computer. Recent versions of Firefox, Safari, Chrome, and Opera all support @font-face linking to TTF and OTF fonts. These font formats are very easy to set up and work well. However, these are considered raw font formats and they lack compression which means longer download times. Perhaps more importantly, they are not encrypted. Most font foundries don&#8217;t allow their fonts to be linked with these formats, since unencrypted font formats make font piracy easier.</p>
<h4>Web Open Font Format (WOFF)</h4>
<p>
        <a target="_blank" href="http://people.mozilla.com/~jkew/woff/woff-spec-latest.html">WOFF</a>, or Web Open Font Format, is a recent format that is an open standard very similar to TTF and OTF. WOFF improves on TTF and OTF by employing compression which helps reduce download times. It also features a special PrivateData entry in the font header that allows a foundry to insert copyright and licensing information. While this gives the foundry more control over WOFF than they have with TTF or OTF, it doesn&#8217;t actually encrypt the font. It&rsquo;s important to note that many foundries have publicly announced support for the WOFF format, but that doesn&#8217;t mean they actually license it for @font-face linking. WOFF has recently been submitted to the W3C as a formal standard, so we may be seeing broader support in the future.</p>
<h4>SVG</h4>
<p>Some browsers support SVG, or Scalable Vector Graphics, for rendering fonts. The results often look nice, but there are accessibility, usability, and security concerns. This format should only be used as a last resort or in very controlled situations.</p>
<h4>Browser Support</h4>
<p>@font-face is supported in recent versions of all major browsers in at least one of the aforementioned formats. As long as your font license allows web linking to these formats, you can reliably support 90%-95% of all browsers today. And that number is only going to rise as users upgrade their browsers. If it&#8217;s important that you reach the remaining 5%-10% of your audience today, you can use a fallback technique and serve those users sIFR or Cufon.</p>
<p>    <well_formed_html></p>
<table style="text-align: center">
<tr>
<td><img src="/article-assets/images/web-fonts-what-to-know/browser-ie.png" style="width: 100px; margin: 0 auto 8px auto;"><strong>IE</strong><br />
                    <br />
                    <span style="color: #666;">version 4+</span></td>
<td><img src="/article-assets/images/web-fonts-what-to-know/browser-firefox.png" style="width: 100px; margin: 0 auto 8px auto;"><strong>Firefox</strong><br />
                    <br />
                    <span style="color: #666;">version 3.5+</span></td>
<td><img src="/article-assets/images/web-fonts-what-to-know/browser-chrome.png" style="width: 100px; margin: 0 auto 8px auto;"><strong>Chrome</strong><br />
                    <br />
                    <span style="color: #666;">version 4+</span></td>
<td><img src="/article-assets/images/web-fonts-what-to-know/browser-safari.png" style="width: 100px; margin: 0 auto 8px auto;"><strong>Safari</strong><br />
                    <br />
                    <span style="color: #666;">version 3.1+</span></td>
<td><img src="/article-assets/images/web-fonts-what-to-know/browser-opera.png" style="width: 100px; margin: 0 auto 8px auto;"><strong>Opera</strong><br />
                    <br />
                    <span style="color: #666;">version 10+</span></td>
</tr>
<tr>
<td>Embedded Open Type (.eot)</td>
<td>True Type (.ttf), Open Type (.otf),Web Open Font Format (.woff)</td>
<td>True Type (.ttf), Open Type (.otf)</td>
<td>True Type (.ttf), Open Type (.otf)</td>
<td>True Type (.ttf), Open Type (.otf)</td>
</tr>
</table>
<p>    </well_formed_html></p>
<h3>
        <a name="head4" class="section">@font-face Implementation</a><br />
    </h3>
<p>Read our companion article <a href="/library/2010/font-face-the-easiest-way-to-use-custom-fonts/">@font-face: The Easiest Way to Use Custom Fonts on Your Web Site</a> for a step-by-step description of how to implement @font-face on your web site.</p>
<h3>
        <a name="head5" class="section">Fluid Font Stack</a><br />
    </h3>
<p>Now that we know about @font-face let&#8217;s discuss using a fluid font stack. If you&#8217;ve worked with CSS, then you&#8217;ve probably seen the typical font stack:</p>
<pre>
        <code>
.title {
	font-family: arial, helvetica, sans-serif;
}
</code>
    </pre>
<p>Look familiar? The browser is simply going to step through this list of fonts and use the first one that it finds installed on the user&#8217;s machine. If we want to use a custom font, our CSS might look something like this:</p>
<pre>
        <code>
@font-face {
	font-family: 'museo-slab';
	src: url('museoslab.ttf') format('truetype');
}

.title {
	font-family: museo-slab, arial, helvetica, sans-serif;
}
</code>
    </pre>
<p>In this case, the @font-face rule defines a font-family which we&#8217;ve named &#8216;museo-slab&#8217; which in turn uses the font on our server named &lsquo;museo-slab.ttf&rsquo;. When the browser reads the class with the font-family property, it knows to download the &#8216;museo-slab.ttf&#8217; font from the server instead of skipping over it. While the font is being downloaded, some browsers will move on to the next font and use that until the download is complete. This means that it&#8217;s more important than ever to use fonts with similar width and kerning so that the shift in text isn&#8217;t so harsh. Consider the following image showing a line of text at the same size and weight, but using different fonts, resulting in different sentence lengths:</p>
<div align="center">
        <img src="/article-assets/images/web-fonts-what-to-know/font-stack.png" border="0" alt="Fig. 2: Font Stack">
<p class="figure">
            <b><br />
              Figure 2:<br />
            </b> Using different font faces can result in different text widths.</p>
</p></div>
<p>When using @font-face, rather than choosing a stack of similarly styled fonts, you may wish to choose a stack of similar width fonts. These fonts should adhere to the following order: custom web font, web-safe font, core font, and finally a generic font. Read our companion article &#8220;Web Font Realities &#8211; A Case Study in Implementing Custom Fonts on a Modern Web Site&#8221; for one example of choosing a fluid font stack in conjunction with @font-face.</p>
<h3>
        <a name="head6" class="section">Licensing Issues When Using Custom Fonts on the Web</a><br />
    </h3>
<p>Now that you understand @font-face and how to use it, let&#8217;s talk about licensing. The first thing to understand is that desktop licensing is different from web licensing. A typical desktop license allows the font to be installed on a fixed number of computers, and it can be used on multiple projects for a one time license payment.</p>
<p>Most web licenses only allow a font to be used on a single web domain, and are typically licensed through a subscription payment with tiered pricing based on how much traffic comes to your web site. This can be further complicated depending upon whether you intend to use the font to simply display content, or if you are going to use the font in some type of web application that will allow end users to use the font in some way (for example, a custom t-shirt design application). Font foundries have different licenses for each of these uses.</p>
<p>Web licensing is really the issue that is preventing @font-face from wider implementation today. In order to use a font across all browsers, the foundry&#8217;s license must allow linking to unencrypted font files (TTF, OTF, WOFF). Most foundries simply do not allow this because unauthorized end users could download and use those fonts on their desktop. Before using @font-face, be sure to check the End User License Agreement (EULA) at the font foundry&#8217;s web site to determine what formats of web linking they allow, if any. You may need to contact a sales rep as web licensing is typically more complicated than desktop licensing, and there are some foundries that do not allow web linking in any format.</p>
<p>A great source of free fonts that do allow all formats of @font-face linking is Font Squirrel. It&#8217;s important to understand that just because a font is free to download and use on your desktop, that doesn&#8217;t necessarily mean that it&#8217;s free to use on the web. Font Squirrel has done the hard work of locating quality free fonts that do allow web linking. Read our companion article <a href="/library/2010/font-face-the-easiest-way-to-use-custom-fonts/">@font-face: The Easiest Way to Use Custom Fonts on Your Web Site</a> for a detailed explanation of how to implement @font-face on your site.</p>
<h4>Fonts as a Service</h4>
<p>If web licensing sounds too complicated, or your font&#8217;s EULA doesn&#8217;t allow font linking, you should investigate font service bureaus. Service bureaus handle all the licensing issues for you, host the fonts, and provide you with some simple CSS and Javascript that enable you to use @font-face as already described. Some foundries act as their own service bureau, and some bureaus are independent and offer fonts from numerous foundries. Browser support is usually very good, reaching about 90%-95% of all users. Font service bureaus can simplify your setup process, but there is typically a subscription payment model based on bandwidth, and you will be relying on a third party service to serve your fonts.</p>
<p>Here is a short list of foundries and font service bureaus:</p>
<ul>
<li>
            <a target="_blank" href="http://code.google.com/webfonts">Google</a> &#8211; Small collection of open source fonts</li>
<li>
            <a target="_blank" href="http://typekit.com/">Typekit</a> &#8211; Numerous mid-size and small foundries</li>
<li>
            <a target="_blank" href="http://kernest.com/">Kernest</a> &#8211; Numerous mid-size and small foundries</li>
<li>
            <a target="_blank" href="http://www.ascenderfonts.com/webfonts/">Ascender Web Type</a> &#8211; Monotype, Microsoft, Ascender</li>
<li>
            <a target="_blank" href="http://www.typotheque.com/webfonts">Typotheque</a> Typotheque fonts</li>
<li>
            <a target="_blank" href="http://fontdeck.com/">Fontdeck</a> Numerous mid-size and small foundries</li>
<li>
            <a target="_blank" href="http://webfonts.fonts.com/">Fonts.com Web Fonts</a> &#8211; Monotype, Linotype, ITC, more</li>
</ul>
<h3>
        <a name="head7" class="section">When and Where to Use Web Typography</a><br />
    </h3>
<p>Headers, menus, and callouts are the most common use cases for custom typography and typically the safest to implement. These elements are usually more predictable in their content and behavior. For example, it&#8217;s unlikely that you will need special symbol glyphs in a navigation menu. However, it&#8217;s important to pay extra attention to any elements that may have line wraps. Some browsers will render the content in a default font, and then render the custom font once it has finished downloading. If the default font is wider than the custom font, it may force a line wrap that the custom font does not need. Depending on the browser, this may result in a reflow of the text or an undesired line wrap. This is sometimes called the FoUT, or Flash of Unstyled Text.</p>
<p>Using custom fonts for body text should probably be avoided in most cases. Body fonts are typically rendered at a smaller size than headers and menus. This means your font choices are limited because not all fonts read well at small sizes. Additionally, body copy is less predictable in terms of content &#8211; it may require special symbols, styles, or languages all of which would contribute to a very large font subset (see Internationalization below). In most cases it&rsquo;s better to use a web safe font or core OS font.</p>
<h4>Internationalization</h4>
<p>Internationalization is another aspect to user generated content where @font-face can really shine. Rather than creating different images for each language (in a menu for example), @font-face renders the text using your custom font in the specified language. The one caveat here is file size. In order to support languages other than English, you have to subset your font to include these other languages. This can drastically increase the size of your font file and consequently the user&#8217;s download time. If you are providing content in multiple languages, you&#8217;ll probably want to create a font file subset for each language and only serve up the requested language font file. Fortunately the process of subsetting is easy with a tool like <a target="_blank" href="http://www.fontsquirrel.com/fontface/generator">Font Squirrel&#8217;s @font-face Generator</a>.</p>
<h3>
        <a name="head8" class="section">Conclusion</a><br />
    </h3>
<p>The future of web typography is @font-face, and with the right font (and license) selection you can begin using it today. But just like any new technology, be sure to only use it when appropriate. Headers, menus, and callouts are the most predictable content elements. Make sure to take download times into consideration, subset your fonts appropriately, and test thoroughly. Even though a new standard may emerge in the future that is supported by designers, browser vendors, and foundries, it will most likely simply be a new format that works with @font-face and plays nicely alongside the formats of today.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2010/what-to-know-when-considering-web-fonts/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>@font-face: The Easiest Way to Use Custom Fonts on Your Web Site</title>
		<link>http://www.bluefishgroup.com/2010/font-face-the-easiest-way-to-use-custom-fonts-2/</link>
		<comments>http://www.bluefishgroup.com/2010/font-face-the-easiest-way-to-use-custom-fonts-2/#comments</comments>
		<pubDate>Tue, 22 Jun 2010 11:00:00 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Web Content Management]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=441</guid>
		<description><![CDATA[Introduction Creative typography has long been unavailable to most designers on the web. We&#8217;re stuck with the same old boring fonts installed on all machines: Arial, Times New Roman, Georgia, etc. However, recent advances in browser technology and typographic tools are affording us new opportunities. Font license permitting, with very little effort, you can now [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Introduction</a><br />
    </h3>
<p>Creative typography has long been unavailable to most designers on the web. We&#8217;re stuck with the same old boring fonts installed on all machines: Arial, Times New Roman, Georgia, etc. However, recent advances in browser technology and typographic tools are affording us new opportunities. Font license permitting, with very little effort, you can now choose from hundreds of fonts and still support 90%-95% of today&#8217;s browsers with very little effort. This article will tell you how.</p>
<h3>
        <a name="head2" class="section">Choosing the Right Font</a><br />
    </h3>
<p>If you have the authority to select the font that is used in your project, then your first step is the most important &#8211; choosing a font with the appropriate license. This can be a complicated issue, so if you wish to follow the path of least resistance, then head straight to <a target="_blank" href="http://www.fontsquirrel.com/">Font Squirrel</a> and choose one of the fonts offered on their site. All are free for commercial use in print or on the web. While there are other sources of free fonts on the web, some are of questionable quality. Also keep in mind that free for desktop use doesn&#8217;t necessarily mean free for web use. Font Squirrel has done the hard work of sourcing fonts from all over the web that are not only free for web use, they are of high quality as well.</p>
<div align="center">
        <img src="/article-assets/images/web-fonts-font-face/font-squirrel-logo.png" border="0" alt="Fig. 1: Font Squirrel Logo">
<p class="figure">
            <b><br />
              Figure 1:<br />
            </b> Font Squirrel is a great source of free fonts and the @font-face Generator</p>
</p></div>
<p>If you can&rsquo;t find the right font at Font Squirrel, you&rsquo;re not completely out of luck. Some foundries offer commercial licenses for web fonts, but be sure to carefully check the End User License Agreement (EULA). The license needs to allow something called unencrypted (or raw) font linking (.ttf, .otf, .woff) in order to follow the steps in this article.</p>
<h3>
        <a name="head3" class="section">Generating the Required Files</a><br />
    </h3>
<p>There are many different ways to download the necessary files and code from Font Squirrel, but I&#8217;m going to show you the easiest and safest method that will work with 90%-95% of all browsers. Once you&#8217;ve selected a font at Font Squirrel, download it to your desktop. Font Squirrel offers prepackaged <a target="_blank" href="http://www.fontsquirrel.com/fontface">@font-face Kits</a>, but in this case we&#8217;re just going to download the TTF or OTF file because the @font-face Kit is overkill for our needs. You can simply browse all the fonts until you find one you like, then download the .ttf or .otf file.</p>
<div align="center">
        <img src="/article-assets/images/web-fonts-font-face/font-download.png" border="0" alt="Fig. 2: Font Kit Examples">
<p class="figure">
            <b><br />
              Figure 2:<br />
            </b> Font Squirrel font download vs. Kit download</p>
</p></div>
<p>After downloading the TTF or OTF file, visit their @font-face Generator web tool. Here we&#8217;ll upload our font, select some options, and download some generated files. So, after uploading your font (in our example below, &ldquo;Daniel Regular&rdquo;), here are the selections we want to make:</p>
<div align="center">
        <img src="/article-assets/images/web-fonts-font-face/font-face-generator.png" border="0" alt="Fig. 3: Font Squirrel @font-face generator">
<p class="figure">
            <b><br />
              Figure 3:<br />
            </b> Font Squirrel @font-face Generator</p>
</p></div>
<h3>
        <a name="head4" class="section">Implementing @font-face</a><br />
    </h3>
<p>Click on the &ldquo;Download your Kit&rdquo; button, and Font Squirrel will produce five files &#8211; three font files, a CSS stylesheet, and a demo HTML file. Upload the font files (.eot, .ttf, and .woff) to your server &#8211; these are the font files you&#8217;re going to link to. The HTML and CSS files are simply demo files to help you style your markup appropriately. The CSS file has two rules &#8211; let&rsquo;s take a look at them:</p>
<pre>
        <code>
    @font-face {
    	font-family: 'DanielRegular';
    	src: url(//:) format('no404'), url('daniel.woff') format('woff'), url('daniel.ttf') format('truetype');
    }
    
    @font-face {
    	font-family: 'DanielRegular';
    	src: url('daniel.eot');
    }
    </code>
    </pre>
<p>The first rule is for all browsers except Internet Explorer, and the second rule is only for Internet Explorer. Go ahead and add the first rule to your main stylesheet. Then, create a second stylesheet just for IE and add the second rule there. In your document <code>head</code>, include your primary stylesheet and then your IE stylesheet using conditional comments. For example:</p>
<pre>
        <code>
        &lt;link rel="stylesheet" type="text/css" href="style.css" media="screen" /&gt;
        &lt;!--[if IE]&gt;&lt;link rel="stylesheet" type="text/css" href="style-ie.css" media="screen" /&gt;&lt;![endif]--&gt;
    </code>
    </pre>
<p>So what&rsquo;s going on here? The separate stylesheets and conditional comments ensure that each browser is served the proper font format. The first property inside the @font-face rule is where we define the name of the font. We can call it anything we want, and in this case we&rsquo;re going to call it &lsquo;DanielRegular&rsquo;.</p>
<p>The second line is where we define the location of the font file. In the case of IE, this is the EOT font.</p>
<p>For all other browsers, the second line is a little more interesting. It has three comma delimited value pairs. The first value pair is actually a bit of misdirection for Internet Explorer. Normally, IE will attempt to download the TTF and WOFF files which it can&rsquo;t actually use. That creates an unnecessary HTTP request which we would like to avoid. The syntax of the first value pair will cause IE to bail out and simply use the EOT file already defined, and other browsers will simply ignore it and continue on. The second value pair is the WOFF font file which will be used if the browser supports it (currently only Firefox 3.6). The third value pair is the True Type Font which will be used by Safari, Chrome, Opera, and Firefox 3.5.</p>
<p>After adding the @font-face rules to your CSS, you&#8217;re ready to go. Now when you&rsquo;re defining your font-family elsewhere in your CSS, you can use &lsquo;DanielRegular&rsquo; like this:</p>
<pre>
        <code>
    .title {
    	font-family: DanielRegular, Arial, Sans-Serif;
    }
    </code>
    </pre>
<p>That&rsquo;s it! This method supports Internet Explorer 4+, Firefox 3.5+, Safari 3.1+, Chrome 4+, and Opera 10+. That&#8217;s about 90%-95% of all browsers, and that number is only going to go up. If closing that last 10% gap is important to you, read our companion article <a href="/library/2010/web-font-realities-case-study/">Web Font Realities &#8211; A Case Study in Implementing Custom Fonts on a Modern Web Site</a>.</p>
<h3>
        <a name="head5" class="section">Performance Tuning and Browser Quirks</a><br />
    </h3>
<p>You&#8217;ve got everything you need to begin using web fonts on your site at this point. However, there is some additional performance tuning that you can perform, and there are some dangers you should be aware of.</p>
<p>Because your custom font is not pre-installed on the end user&rsquo;s machine, it must be downloaded from your server to the user&rsquo;s browser which may cause a FOUT, or Flash Of Unstyled Text. The FOUT occurs while the fonts are being downloaded for the first time. Depending on the browser, the user may see either a blank space or a default font until the download is complete. It is therefore important to minimize the download time in order to eliminate or at least reduce the duration of the FOUT.</p>
<h4>File Size</h4>
<p>The first thing to consider is file size. A typical font face is around 50KB of data. Add in bold and oblique faces and you&#8217;ve got 150KB of data the user must download. So make sure that each font you use will bring enough value to the user to justify the additional download time. Once you&rsquo;ve decided on your font faces, the following techniques can help reduce their file size.</p>
<h4>Subsetting</h4>
<p>A typical font face may have hundreds of glyphs, or characters. In addition to the standard latin alphabet, there are numbers, symbols, accented characters, foreign languages, etc.  Subsetting allows you to select only a portion of the total glyphs to include in your font file. The subsetting process is made easy by the Font Squirrel @font-face generator. By default, the generator will use the Mac Roman subset which is more than adequate for most use cases. However, if your web site is only going to display English letters and numbers you should select the Basic Latin subset, cutting the number of glyphs in half and reducing the file size of the font. In our example above, our font was reduced from 53KB to 37KB just by subsetting to Basic Latin.</p>
<h4>Gzip</h4>
<p>In addition to subsetting you can configure your server to deliver the fonts using <a target="_blank" href="http://en.wikipedia.org/wiki/Gzip">Gzip compression</a> (WOFF and EOT are already compressed, so no need to Gzip those) with a future expiry date. Gzip will further reduce the file size and the expiry date will ensure that the user&#8217;s browser will cache the fonts after the initial download. Gzip can give you a 25%-50% savings in file size, so it&#8217;s definitely worth the effort.</p>
<h4>Internet Explorer Quirks</h4>
<p>There are a few special precautions you need to take for Internet Explorer. First, make sure that all the fonts linked in your CSS are actually being used on your site. Internet Explorer will download all files linked from your CSS file whether they are actually used or not.</p>
<p>Second, make sure that your @font-face rule is defined before any <code>&lt;script&gt;</code> tag is encountered. There is a bug in Internet Explorer that will cause @font-face to fail if the <code>&lt;script&gt;</code> tag is encountered first. CSS before Javascript is a good practice in general.</p>
<h4>Targeted Downloads</h4>
<p>As with any other file that must be downloaded by the user (CSS, Javascript, images), target your font downloads appropriately. If the font is used site wide, it makes sense to include the @font-face in your global CSS. However, if the font is only used by a few pages on the site, then it makes sense to create a specific CSS file just for those pages.  That way the font will only be downloaded by users that visit those specific pages.</p>
<h4>URI Encoding</h4>
<p>I also recommend that you do not URI encode your fonts. It&#8217;s possible to use Base64 encoding to store your font files in CSS, but this can actually increase the size of the font. Additionally, because URI encoded fonts are generally stored in a single CSS file the browser will download all the different formats whether it can use them or not.</p>
<h4>Local SRC</h4>
<p>You may have noticed that there are three styles of CSS in the Font Squirrel @font-face generator. I recommend the Mo&rsquo; Bulletproof method because it avoids using a local source reference. Using a local source can theoretically improve performance because the browser will look for the font on the end user&rsquo;s machine, but it&rsquo;s been reported that Opera can crash in certain situations (my own testing has confirmed this). It&rsquo;s also possible that a user might have a corrupt font which could potentially cause problems. Ultimately, it&rsquo;s simply safer to deliver the font from your own server over which you have complete control.</p>
<h4>Testing</h4>
<p>Finally, it&#8217;s very important to test. @font-face is an emerging technology with behavioral and rendering variations between browsers. Make sure you test all the major browsers on both Mac and Windows platforms and continue testing as new browser versions are released.</p>
<h3>
        <a name="head6" class="section">Conclusion</a><br />
    </h3>
<p>Thanks to modern browser support for the @font-face rule and tools like Font Squirrel&rsquo;s @font-face Generator, creative typography on the web is here today. If you follow the steps outlined above, you&rsquo;ll be able to serve up custom fonts to the majority of your users today in a performant manner. If you&rsquo;d like to read more about Web Typography in general or find out what you can do when your font license isn&rsquo;t quite so liberal, read our companion articles &ldquo;What to Know When Considering Custom Fonts for Your Web Site&rdquo; and &ldquo;Web Font Realities &#8211; A Case Study in Implementing Custom Fonts on a Modern Web Site&rdquo;.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2010/font-face-the-easiest-way-to-use-custom-fonts-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Webinar: Using Alfresco Share as a Corporate Intranet</title>
		<link>http://www.bluefishgroup.com/2010/webinar-using-alfresco-share-as-a-corporate-intranet/</link>
		<comments>http://www.bluefishgroup.com/2010/webinar-using-alfresco-share-as-a-corporate-intranet/#comments</comments>
		<pubDate>Mon, 21 Jun 2010 21:17:37 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Webinars]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=438</guid>
		<description><![CDATA[Blue Fish has been helping clients build Intranets for over ten years, and although this type of project doesn&#8217;t sound that challenging, I think Intranets can be one of the hardest types of projects to get right. What makes Intranets so tricky is that they have to serve several masters. They often have to: Provide [...]]]></description>
				<content:encoded><![CDATA[<p>Blue Fish has been helping clients build Intranets for over ten years, and although this type of project doesn&#8217;t sound that challenging, I think Intranets can be one of the hardest types of projects to get right.</p>
<p>What makes Intranets so tricky is that they have to serve several masters. They often have to:</p>
<ul>
<li>Provide easy access to relevant information when an employee wants it (bottom-up)</li>
<li>Communicate important information to employees whether they want it or not (top-down)</li>
<li>Help teams collaborate amongst themselves in a secure manner (within groups)</li>
</ul>
<p>These competing priorities can make it hard for a single Intranet website to meet all of your company&#8217;s needs. What makes it even worse is that since everyone in the company uses the Intranet, <strong>everyone in the company has an opinion</strong> on what it should look like (even if they don&#8217;t really know much about how to design these types of things).</p>
<p>Luckily, my clients have taught me a few tricks over the years about how to deal with these issues. So this<strong> webinar</strong> discusses some neat ideas for how Alfresco Share can be used as a corporate Intranet, creating a network of Intranet sites that work together to serve different stakeholder needs at different levels of the company.</p>
<p><a href="http://www2.alfresco.com/l/1234/2010-07-01/I340F">Download now!</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2010/webinar-using-alfresco-share-as-a-corporate-intranet/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Alfresco Lunch and Learns in July &#8211; 5 Cities in 3 States</title>
		<link>http://www.bluefishgroup.com/2010/alfresco-lunch-and-learns-in-july-5-cities-in-3-states/</link>
		<comments>http://www.bluefishgroup.com/2010/alfresco-lunch-and-learns-in-july-5-cities-in-3-states/#comments</comments>
		<pubDate>Tue, 22 Jun 2010 02:54:15 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=437</guid>
		<description><![CDATA[Blue Fish and Alfresco are hosting another round of lunch and learns to introduce folks to the benefits of using Alfresco as an Enterprise Content Management platform. If you haven&#8217;t seen Alfresco yet, let us buy you some lunch and show you what it can do. We&#8217;ll be hosting these events in 5 cities across [...]]]></description>
				<content:encoded><![CDATA[<p>Blue Fish and Alfresco are hosting another round of lunch and learns to introduce folks to the benefits of using Alfresco as an Enterprise Content Management platform. If you haven&#8217;t seen Alfresco yet, let us buy you some lunch and show you what it can do.</p>
<p>We&#8217;ll be hosting these events in 5 cities across 3 states:</p>
<ul>
<li><b>Austin, TX</b> &#8211; Tuesday, July 13 &#8211; <a href="http://www.alfresco.com/about/events/lunch-learns/register/?code=lunchlearn_2010_Q2_HOU">Register</a></li>
<li><b>Houston, TX</b> &#8211; Wednesday, July 14 &#8211; <a href="http://www.alfresco.com/about/events/lunch-learns/register/?code=lunchlearn_2010_Q2_AUS">Register</a></li>
<li><b>San Antonio, TX</b> &#8211; Thursday, July 15 &#8211; <a href="http://www.alfresco.com/about/events/lunch-learns/register/?code=lunchlearn_2010_Q2_SAT">Register</a></li>
<li><b>St. Louis, MO</b> &#8211; Tuesday, July 20 &#8211; <a href="http://www.alfresco.com/about/events/lunch-learns/register/?code=lunchlearn_2010_Q2_SLS">Register</a></li>
<li><b>Orlando, FL</b> &#8211; Tuesday, July 27 &#8211; <a href="http://www.alfresco.com/about/events/lunch-learns/register/?code=lunchlearn_2010_Q2_MCO">Register</a></li>
</ul>
<p>This round of lunch and learns will provide an overview of Alfresco and describe how companies like yours are using Alfresco to address their ECM challenges at a fraction of the cost of traditional solutions. I&#8217;ll be at each and every one of them, and I&#8217;m planning to give a live demo, so wish me luck that the demo gods favor me on those days.</p>
<p>Space is limited, so please <strong>register early</strong> to secure your place. I hope to see you there.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2010/alfresco-lunch-and-learns-in-july-5-cities-in-3-states/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Alfresco Enterprise 3.3 Now Available</title>
		<link>http://www.bluefishgroup.com/2010/alfresco-enterprise-33-now-available/</link>
		<comments>http://www.bluefishgroup.com/2010/alfresco-enterprise-33-now-available/#comments</comments>
		<pubDate>Fri, 04 Jun 2010 22:49:55 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=436</guid>
		<description><![CDATA[There wasn&#8217;t much fanfare about it, but Alfresco Enterprise 3.3 was released last week. The Community edition has been available for over a month, and now the fully supported Enterprise edition is available. You can download a trial of Alfresco Enterprise here.]]></description>
				<content:encoded><![CDATA[<p>There wasn&#8217;t much fanfare about it, but Alfresco Enterprise 3.3 was released last week. The Community edition has been available for over a month, and now the fully supported Enterprise edition is available.</p>
<p>You can <a href="http://www.alfresco.com/products/ecm/enttrial/">download a trial of Alfresco Enterprise here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2010/alfresco-enterprise-33-now-available/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Webinar: Documentum Migration Success Story</title>
		<link>http://www.bluefishgroup.com/2010/documentum-migration-success-story-webinars/</link>
		<comments>http://www.bluefishgroup.com/2010/documentum-migration-success-story-webinars/#comments</comments>
		<pubDate>Wed, 02 Jun 2010 09:38:48 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Webinars]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=432</guid>
		<description><![CDATA[Blue Fish is hosting a couple of webinars in the next two weeks that feature Blue Fish clients talking about the methods they have used to successfully perform Documentum Migrations. The first webinar is Extreme Migration Makeover, and it was presented at EMC World by Bas Ursem with Solvay Pharmaceuticals. It&#8217;s Wednesday June 9th at [...]]]></description>
				<content:encoded><![CDATA[<p>Blue Fish is hosting a couple of webinars in the next two weeks that feature Blue Fish clients talking about the methods they have used to successfully perform Documentum Migrations.</p>
<p>The first webinar is <strong><a href="http://www.bluefishgroup.com/wp-content/uploads/landing/mwb/lib/playback.html">Extreme Migration Makeover</a></strong>, and it was presented at EMC World by Bas Ursem with Solvay Pharmaceuticals. It&#8217;s <strong>Wednesday June 9th</strong> at 10:00 CDT (Chicago Time). If you are planning a content migration project, this webinar may be a must-see. It may be particularly important to you if…</p>
<ul>
<li>you are worried about system down time, or</li>
<li>you are under the gun to do your migration on a short time line, or if</li>
<li>you are afraid that the migration may be a lot harder than it appears on the surface.</li>
</ul>
<p>And if that’s not exciting enough, another friend of ours, Nils Schlote with Roche, will be presenting a related topic, on <strong>Thursday 17 June </strong>at 10:00 CDT. Roche has a roadmap with a myriad of new systems, upgrades and consolidations so they have devised a global migration strategy that will enable project teams to address their unique migration challenges in a consistent, repeatable manner.</p>
<p>This presentation may be particularly interesting to you if…</p>
<ul>
<li>your company seems to always be doing migrations, or</li>
<li>you are worried about a barrage of upgrades and consolidations coming down the pipe, or if</li>
<li>you are struggling to get your arms around a global strategy.</li>
</ul>
<p>You can watch more webinars <a href="http://www.bluefishgroup.com/resources/webinars-presentations/">here.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2010/documentum-migration-success-story-webinars/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>EMC World 2010 &#8211; Bas Ursem is a Rock Star</title>
		<link>http://www.bluefishgroup.com/2010/emc-world-2010-bas-ursem-is-a-rock-star/</link>
		<comments>http://www.bluefishgroup.com/2010/emc-world-2010-bas-ursem-is-a-rock-star/#comments</comments>
		<pubDate>Wed, 12 May 2010 17:08:16 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=431</guid>
		<description><![CDATA[I just finished attending Bas Ursem&#8217;s presentation on how Solvay Pharmaceuticals (now Abbot) migrated from a legacy Documentum system into a new Documentum/SharePoint system. This was the first project to use Migration Workbench, and Bas told the story of how they used a combination of process and technology to overcome some steep migration challenges. The [...]]]></description>
				<content:encoded><![CDATA[<p>I just finished attending Bas Ursem&#8217;s presentation on how Solvay Pharmaceuticals (now Abbot) migrated from a legacy Documentum system into a new Documentum/SharePoint system. This was the first project to use <a href="http://www.bluefishgroup.com/content-migrations/migration-workbench.php">Migration Workbench</a>, and Bas told the story of how they used a combination of process and technology to overcome some steep migration challenges.</p>
<p>The room was full of people from life sciences companies, and they seemed to hang on every word. EMC World doesn&#8217;t have very many presentations like this on real-world case studies, and from what I saw, there is incredible demand for them. Attendees really want to hear and talk to companies that have been through these types of projects before. We are all hoping EMC gets the message and includes more case study presentations in the future.</p>
<p><b>Bas is a great speaker.</b> He was able to turn a detailed presentation about migrating regulated pharmaceutical content into a fun and interesting session. At the end of the session, Bas rewarded folks that asked questions by giving them &#8220;goodies&#8221; that he had brought over from The Netherlands (one was a toy bus that fit the theme of the presentation, and the other was a bottle opener in the shape of a Dutch wooden shoe). </p>
<p>If you weren&#8217;t able to make it to EMC World, or If you were there but missed his session, you can catch an &#8220;encore presentation&#8221; of Bas&#8217; session in June. Bas will be repeating his presentation on a webinar that you can stream over the Internet. If you are interested in seeing it, or you want to share it with a colleague, you can click here to <a href="http://www.bluefishgroup.com/landing/solvay-webinar.php">register for Solvay Pharmaceuticals: Extreme Migration Makeover!</a> on June 9th.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2010/emc-world-2010-bas-ursem-is-a-rock-star/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>EMC World 2010 &#8211; More Information on Documentum Search Services</title>
		<link>http://www.bluefishgroup.com/2010/emc-world-2010-more-information-on-documentum-search-services/</link>
		<comments>http://www.bluefishgroup.com/2010/emc-world-2010-more-information-on-documentum-search-services/#comments</comments>
		<pubDate>Wed, 12 May 2010 16:36:53 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=430</guid>
		<description><![CDATA[I attended Aamir Farooq&#8217;s session devoted to Documentum Search Services (DSS) and found out a few more details. Aamir did a great job giving a good level of detail and connecting the technical points to the benefits that DSS users will see, and he did so in a laid back, easy to consume manner. In [...]]]></description>
				<content:encoded><![CDATA[<p>I attended Aamir Farooq&#8217;s session devoted to Documentum Search Services (DSS) and found out a few more details. Aamir did a great job giving a good level of detail and connecting the technical points to the benefits that DSS users will see, and he did so in a laid back, easy to consume manner. </p>
<p>In no particular order, here are the things that stood out for me: </p>
<h3>One Box Search Improved </h3>
<p>The default search behavior will switch from &#8220;OR&#8221; syntax to &#8220;AND&#8221; syntax when you search for more than one word. Imagine that you search for &#8220;bear&#8221; and get 10,000 results, so you decide to be more specific by searching for &#8220;black bear&#8221;. In the FAST search engine, you might get back 100,000 results (all the documents containing either &#8220;black&#8221; or &#8220;bear&#8221;). In DSS, you would get back fewer results, since DSS returns only the documents that contain both &#8220;black&#8221; and &#8220;bear&#8221;. This is how Google and other internet search engines work, so it&#8217;s more intuitive for your users. </p>
<h3>Optimized for Documentum Use Cases </h3>
<p>Because EMC now has control over the internals of their search engine, they are able to optimize it for some of the key Documentum use cases. First, they optimized the ability to exclude results that the user doesn&#8217;t have permission to see. Queries that used to take minutes in FAST now take seconds in DSS. Second, they optimized the &#8220;folder descend&#8221; queries that search inside deep folder structures. In FAST, a query that took 44 seconds now takes less than 1 second in DSS. </p>
<h3>Native Support for Facets </h3>
<p>Faceted search refinement is something I&#8217;ve been excited about for about 5 years. For the uninitiated, this technology allows users to quickly refine large search result sets by drilling down on pre-defined filters (or facets). This approach is used by Amazon, Home Depot, and lots of other online retailers. </p>
<p>For example, if you search for &#8220;drug interaction&#8221; and get back 10,000 results, you can quickly refine that list to, say, only Word documents by drilling down on the file format facet. This might limit the results to 1,000 documents. Then you might refine on the document type facet, showing only the reports. That might limit the results to 100 documents. Refine by date modified to selecting only the documents created in the past week, and it will be easy to find the document you are looking for in the small number of  documents remaining. </p>
<p>DSS supports facets out of the box, so Webtop, CenterStage, and other Documentum products can have much improved search interfaces. </p>
<h3>No Additional Cost </h3>
<p>Because DSS is part of the Content Server, it is available at no additional cost to existing Documentum customers with a current maintenance contract. </p>
<h3>You Must Plan on Upgrading Next Year (2011)</h3>
<p>Because Microsoft is no longer supporting FAST as an OEM product, EMC has some pretty aggressive timelines for replacing FAST with DSS. Support for FAST expires at the end of 2011, so if you want to be on a supported product, you&#8217;ll have to install DSS before then. </p>
<p>This might mean that you have to upgrade Documentum, since DSS will only work on D6.5 SP2 and later. So be sure to plan your budgets next year for the hardware and personnel necessary to perform the upgrade. </p>
<p>The good news is that the upgrade should be a lot less painful than the last time they replaced Documentum&#8217;s full-text engine. DSS can be installed alongside FAST (on different servers, but as part of the same Documentum environment). While it is indexing all of your content, you can keep using FAST. When you are ready, you can cut over from FAST to DSS pretty painlessly.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2010/emc-world-2010-more-information-on-documentum-search-services/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>EMC World 2010 &#8211; xCP is Taking Over the (EMC) World</title>
		<link>http://www.bluefishgroup.com/2010/emc-world-2010-xcp-is-taking-over-the-emc-world/</link>
		<comments>http://www.bluefishgroup.com/2010/emc-world-2010-xcp-is-taking-over-the-emc-world/#comments</comments>
		<pubDate>Wed, 12 May 2010 03:08:31 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=429</guid>
		<description><![CDATA[Documentum&#8217;s xCelerated Composition Platform (xCP) is the hot new thing at EMC World this year. I attended John McCormick&#8217;s xCP Roadmap presentation to learn what&#8217;s new in xCP and what&#8217;s coming. So what is xCP does and why ECM feel it&#8217;s necessary? xCP is trying to solve two problems: It&#8217;s hard to upgrade Documentum solutions [...]]]></description>
				<content:encoded><![CDATA[<p>Documentum&#8217;s xCelerated Composition Platform (xCP) is the hot new thing at EMC World this year. I attended John McCormick&#8217;s xCP Roadmap presentation to learn what&#8217;s new in xCP and what&#8217;s coming. </p>
<p>So what is xCP does and why ECM feel it&#8217;s necessary? xCP is trying to solve two problems:</p>
<ul>
<li>It&#8217;s hard to upgrade Documentum solutions because there are so many customizations that need to be migrated to the new version</li>
<li>There is a class of important ECM challenges (managing what EMC calls &#8220;cases&#8221;) that are not being well served with traditional ECM solutions</li>
</ul>
<h3>What is a Case?</h3>
<p>A case is the term EMC is using to describe the collection of information (structured and unstructured) that goes through a business process in order to reach a business decision. It might include multiple documents, some data from an external system, and some data captured from participants in the process. All this data has to come together in order for some important decision to be made. </p>
<p><i>Case Management</i> is the creation, routing, collaboration on, and monitoring of these case materials. It includes the orchestration of various interactions that are needed to make an optimal business decision. If a case is a file folder full of documents, case management is the set of processes that makes sure the folder goes to the right people and gets filled up with the right documents. </p>
<p>For example, imagine that you are a mortgage company and someone applies for a loan. They fill out a form and give it to a loan administrator. Based on the type of loan being requested and the amount, the load administrator requests a credit report, tax documents and other financial information. Once all of that has been gathered, the loan administrator passes the file over to the loan approver with the ability to approve a loan of that amount. This person looks over all the information, requests some additional documents (maybe a survey or an appraisal) and then approves or denies the loan. There are lots of other steps in the process &#8211; you get the picture.  </p>
<p>Collecting all these documents and forwarding them to the right people so that the best decisions can be made is what xCP is trying to automate. </p>
<p>Case-related processes have some unique attributes that make them challenging to automate:</p>
<ul>
<li><b>They are non-deterministic</b> &#8211; You can&#8217;t predict ahead of time the exact process that a case will follow</li>
<p> 
<li><b>They are driven by human decision making</b> &#8211; the next step in the process is often decided by the person performing the current step</li>
<li><b>They are also driven by content status</b> &#8211; cases can&#8217;t proceed to the next step in the process until all the necessary information has been provided, and often the next step is determined by some attribute of the content (or metadata about the case itself)</li>
<p> </ul>
</p>
<p>Case management fits in a gray area between ad-hoc collaboration where pre-defined workflows just aren&#8217;t effective and transactional document management with strict, linear processes like scanning invoices. When you have a process with lots of variation and lots of pieces of information coming together, you probably have a case management problem. </p>
<h3>How Does xCP Help Companies Manage Cases?</h3>
<p>EMC&#8217;s vision is to make it easy for companies to design and deploy custom case management solutions that are tailored for their specific business processes. With xCP,<br />
the idea is that you can easily define a case (with all its metadata and associated content), design forms that are need to capture structured data, and model the business processes that the case goes through. </p>
<p>Once you have completed these design and modeling activities, xCP will automatically assemble a custom application with work queues, custom forms, work flows, and every thing else needed for your users to create and manage cases. In effect, you are building a custom application without writing any code. </p>
<p>And this is where the other key goal of xCP comes in &#8211; making it much easier to upgrade Documentum without breaking your custom application. </p>
<h3>Preventing Upgrade Headaches Using a Declarative Model</h3>
<p>One of the common complaints about Documentum is that when you customize it to meet your needs, it&#8217;s likely that your customizations will not work when the next version of the product comes along. This problem isn&#8217;t unique to Documentum &#8211; it&#8217;s common to all enterprise software applications. </p>
<p>This is a problem I know a lot about. Blue Fish builds custom applications on top of Documentum all the time (it&#8217;s our sweet spot), and while we have developed best practices to insulate our customizations from changes in the platform, sometimes it simply can&#8217;t be avoided. If you write an application in WDK and a couple of years later, EMC gets rid of WDK, you are pretty much screwed. </p>
<p>EMC&#8217;s approach to eliminating customization-related upgrade hassles is to eliminate the customizations themselves. They do this in xCP with what&#8217;s called a declarative model. WIth a declarative model, you express <i>what</i> you want the system to do, not <i>how</i> it should go about doing it. </p>
<p>Here&#8217;s how it works. Let&#8217;s say you need a form to capture the loan application we described earlier. With xCP, you use Forms Builder to drag the various fields onto a form and click various checkboxes to specify which fields are mandatory and such. Forms Builder saves this layout in an internal format that xCP interprets at runtime when it&#8217;s time to display the form. </p>
<p>A year or two later, imagine that EMC completely changes the architecture of xCP, migrating it from a WDK application to a rich internet application like CenterStage. You shouldn&#8217;t have to redefine your form, because the new version of xCP will be able to read that same form layout file, and even though the form will look completely different in the new version of xCP, it will have all the same fields in the same layout. </p>
<p>By the way, this example isn&#8217;t that far-fetched. EMC is in the process of doing this very thing! When xCP 2.0 is released next year, it will be completely re-implemented using a rich internet application toolkit like ExtJS. But John promises that you won&#8217;t have to change any of your forms definitions, process definitions, data models, or any of the other xCP components that define your case management solution. </p>
<p>It&#8217;s important to note that this approach means you can&#8217;t customize xCP. If there isn&#8217;t a form control that you need, you&#8217;ll be out of luck. If the xCP designers didn&#8217;t anticipate your use case, you&#8217;re probably out of luck. If you don&#8217;t like the look and feel of the UI or the performance of the system, you&#8217;re out of luck. And while that might be scary for a crotchety old developer like me, for most of EMC&#8217;s customers, it&#8217;s a tradeoff they will gladly accept if it means fewer upgrade headaches.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2010/emc-world-2010-xcp-is-taking-over-the-emc-world/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>EMC World 2010 &#8211; Documentum  Architecture Updates</title>
		<link>http://www.bluefishgroup.com/2010/emc-world-2010-documentum-architecture-updates/</link>
		<comments>http://www.bluefishgroup.com/2010/emc-world-2010-documentum-architecture-updates/#comments</comments>
		<pubDate>Tue, 11 May 2010 04:08:58 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=428</guid>
		<description><![CDATA[Victor Spivak gave his annual Documentum Architecture presentation today. The main themes he covered were Service Orientedness (my term), Enterprise Readiness, and Complexity Reduction. He also dropped a real bombshell about a potential change in the architecture. Service Orientedness Documentum Foundation Services (DFS) is Documentum&#8217;s web services API. It&#8217;s been around for a few years, [...]]]></description>
				<content:encoded><![CDATA[<p>Victor Spivak gave his annual Documentum Architecture presentation today. The main themes he covered were Service Orientedness (my term), Enterprise Readiness, and Complexity Reduction.</p>
<p>He also dropped a real bombshell about a potential change in the architecture.</p>
<h3> Service Orientedness </h3>
<p>Documentum Foundation Services (DFS) is Documentum&#8217;s web services API. It&#8217;s been around for a few years, and EMC is promoting as the best way to interact with the Content Server. Developers are encouraged to use DFS instead of Documentum Foundation Classes (DFC), which they now consider a low-level API. You use DFC to create services, and you use DFS to create applications. </p>
<p>EMC is taking this advice to heart. Centerstage and Media Workspace are two recent Documentum products that are built on DFS (as opposed to Webtop, which is built using DFC). </p>
<p>There are 30 Core Services in DFS, but not all the functionality in Documentum is exposed through DFS. They only add the services that they need (or for which there is popular demand). </p>
<p>DFS is a SOAP-based web service, which is suitable for strongly typed languages such as Java and C#, but is apparently not so good for dynamic languages like Ruby or JavaScript. Developers that use dynamic languages prefer RESTful web services, which EMC does not currently support. </p>
<p>Victor is a fan of RESTful services, and he was looking for some support from the attendees that he could use to convince his managers to invest in adding support for REST. Victor asked how many people would really use RESTful services if he were to build them, and in a room of over 200 people, only TEN raised their hands. Victor was crestfallen. </p>
<p>This raises a question. Why don&#8217;t Documentum developers care about REST when other developers in other fields are so passionate about it? My (completely speculative) opinion is that the day of the Documentum developer is mostly behind us. Most people in the room were Documentum <i>implementers</i>, not developers. They are not tasked with building interesting new applications that mash-up data from different sources while integrating the result into some internal portal or other kind of web application. They don&#8217;t spend all day every day developing, so they don&#8217;t value using scripting languages like JavaScript to decrease development time. </p>
<p>Contrast this with Alfresco&#8217;s developer community, which is as likely to be building a content-enabled web application as they are to simply implement the technology as a document repository for their office documents. As a result, Alfresco&#8217;s SOAP API has being placed on the back burner while their RESTful services get constant attention. </p>
<h3> CenterStage &#8211; An Example of Using DFS </h3>
<p>Victor cited Centerstage as the shining example of how EMC wants to build apps from now on. </p>
<p>He noted that one of the big limitations of WDK is that it does not separate presentation logic from application logic. This is a problem because presentation technologies evolve  very quickly, changing every couple of years. Keeping up with these changes would mean re-writing the entire application constantly, but ignoring these changes makes your application seem outdated and clunky. </p>
<p>With Centerstage, the presentation logic lives in the browser, while the application logic lives on the server. EMC uses a JavaScript toolkit to make requests to the DFS services which return their results as XML files. The browser then renders the user interface by parsing the XML file as a data file. This is different from WDK which generates the UI on the server, renders HTML files and the browser simply displays the HTML file. </p>
<p>One of the benefits of this approach is that it allows the presentation tier to use a mix of technologies, such as Ajax and Flex. Centerstage is mostly a JavaScript application, but it has a few Flex components for doing things like viewing thumbnails. </p>
<p>Because DFS is a SOAP-based web service, and those are hard to use in applications like this, EMC has written their own middle tier in the browser. This allows the browser to use direct web remoting (DWR) to communicate with DFS. </p>
<p>Victor told us about a couple of interesting technology decisions they made. When Centerstage began development 3 years ago, <a href="http://www.extjs.com/">ExtJS</a> was the JavaScript toolkit they chose. But if they were to make the decision today, they would probably use <del datetime="2010-05-15T13:06:16+00:00"><a href="http://www.webtoolkit.eu/jwt">JWt (Java Web Toolkit)</a></del> <a href="http://code.google.com/webtoolkit/">GWT (Google Web Toolkit). </p>
<p>The other interesting decision they made was to use <a href="https://developer.mozilla.org/En/XUL">Mozilla XUL</a> to define the layout of their user interface. Then they translate the XUL XML file into ExtJS in the browser via XSLT. </p>
<h3> Enterprise Readiness </h3>
<p>A big focus area for Documentum 6.6 was to improve what EMC calls &#8220;Enterprise Readiness&#8221;, which I took to mean &#8220;making it easier for big giant enterprises to run and support Documentum.&#8221; </p>
<p>One way they have done this is to improve Documentum&#8217;s ability to ingest very large volumes of data. Version 6.5 is already very good at this, and with 6.6, they are making it even better. </p>
<p>In version 6.5, Documentum added batching (importing multiple documents in a single batch), scoping (batching related documents together), partitioning (storing related documents together), and lightweight sysobjects (storing fewer attributes when the complete set of metadata is not needed). Together, they allow Documentum to ingest 5 times as many documents in an hour than in previous versions.  </p>
<p>In version 6.6, Documentum has improved the batching and partitioning and has added some additional improvements: </p>
<ul>
<li>True null support &#8211; reduces the storage required for attributes with no value</li>
<li>Use of small int (2 bytes) and tiny int (1 byte) where possible to save database storage</li>
<li>Storing boolean values more efficiently to save storage space</li>
<li>Storing ID attributes more efficiently in MS SQL Server</li>
</ul>
<p>Documentum also added some DQL Enhancements that improve sub-selects and joins (they added support of <a href="http://en.wikipedia.org/wiki/Join_(SQL)#Left_outer_join">left outer joins</a>). </p>
<p>I&#8217;m excited about the new support in DQL for pagination, or returning only a certain subset of the rows that result from the query. This is useful in web applications when you have &#8220;pages&#8221; of results that you want to the user to navigate through. </p>
<p>In the past, you had two options, neither of them good. You could keep the database cursor open and wait for the user to request the next page of results (this is expensive and you never know if the user is going to request another page or not). Or you could rerun the entire query and manually discard the rows that you&#8217;ve already returned. Pagination lets you rerun the query each time while specifying row number to start with. DQL will only return the small result set you want to show to the user.  </p>
<h3> Documentum Search Services </h3>
<p>Documentum is releasing a new search engine called Documentum Search Services (DSS). This will replace the FAST search engine. Apparently, FAST makes it much too difficult to support a really large number of documents (100 million+). </p>
<p>DSS stores the metadata in xDB (EMC&#8217;s XML database) and the full text index in Lucene. This allows it to issue queries across both metadata and full text very quickly. One advantage is that since xDB contains all the ACL metadata, it can weed out any results that the user does not have permission to see. With FAST, each item in the search result had to be checked against the Content Server&#8217;s ACL metadata before it was returned to the user. EMC says that this alone makes DSS 10 times faster. </p>
<p>DSS has other &#8220;enterprise readiness&#8221; features as well.</p>
<ul>
<li>It provides low-cost high availability (n+1 servers instead of 2n servers)</li>
<li>Support for vmware (FAST didn&#8217;t support it)</li>
<li>Support for NAS</li>
<li>Support for Disaster recovery</li>
<li>If you are running a distributed architecture, less data will be shipped across the wide area network during indexing because the text extraction takes place at the remote server and only the &#8220;raw text&#8221; is sent across the WAN to DSS</li>
</ul>
<h3> Other Platform Improvements in 6.6 </h3>
<ul>
<li>Documentum added support for ATMOS, EMC&#8217;s cloud storage solution. </li>
<li>Java Messaging Service (JMS) will failover will to a JMS server on other content server if one is available</li>
<li>DCTM Messaging Service will now failover (this is mostly used in distributed content architectures) </li>
<li>6.6 adds Kerberos support at the content server, DFC, and DFS layers</li>
<li>In response to requests from IT shops that don&#8217;t want to support Java on their Windows desktops, EMC is releasing UCF.net, a pure Microsoft version of Documentum&#8217;s content transfer solution</li>
</ul>
<h3> Complexity Reduction </h3>
<p>The big talk around Momentum is about xCP, Documentum&#8217;s xCelerated Composition Platform. Victor says that everything about xCP is about reducing complexity so that it&#8217;s easier to create and deploy Documentum-powered content applications. He called it the &#8220;Visual Basic of ECM.&#8221;</p>
<p>xCP uses a model driven (declarative) approach to reduce the need to write code. You &#8220;declare&#8221; what you want the application to do (via configuration) and xCP will assemble the application that you have described. </p>
<p>xCP 1.5 is based on WDK, but it&#8217;s being shelved for a new version, xCP 2.0 that will be based on a rich internet application model similar to Centerstage. Victor hinted that the architectural patterns will be similar to Centerstage, but the implementation technologies are likely to be different in xCP 2.0. </p>
<p>Victor called this a &#8220;very ambitious project&#8221;. xCP 2.0 is targeted for the end of next year (2011). </p>
<h3> Documentum Rejecting the Relational Database?</h3>
<p>The final item I&#8217;ll leave you with is the most exciting from an architecture perspective. Victor told us that they have been thinking about ways to use xDB as the metadata storage mechanism for Documentum, replacing the relational database that they use today. </p>
<p>This is 3-5 years away, if it happens at all, but it&#8217;s an incredibly intriguing idea. Eliminating the database would dramatically reduce the complexity and overhead required to operate a large, distributed Documentum environment, and while Victor said that he personally thinks it&#8217;s the right thing to do, there is a lot of thinking and testing to be done first. He has a small team working on it now, and Victor told the audience that while he&#8217;s making no promises, he hopes to be standing at an EMC World 2-3 years from now revealing it as an upcoming architectural change. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2010/emc-world-2010-documentum-architecture-updates/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>EMC World 2010 &#8211; Day One Initial Thoughts</title>
		<link>http://www.bluefishgroup.com/2010/emc-world-2010-day-one-initial-thoughts/</link>
		<comments>http://www.bluefishgroup.com/2010/emc-world-2010-day-one-initial-thoughts/#comments</comments>
		<pubDate>Mon, 10 May 2010 18:02:44 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=427</guid>
		<description><![CDATA[It&#8217;s the middle of the first day of EMC World. Here are my thoughts so far. New Name for Content Management and Archiving The division within EMC that owns Documentum has changed their name from Content Management and Archiving to &#8220;Information Intelligence Group&#8221;. Not sure what this is about yet &#8211; I guess I&#8217;ll find [...]]]></description>
				<content:encoded><![CDATA[<p>It&#8217;s the middle of the first day of EMC World. Here are my thoughts so far. </p>
<h3>New Name for Content Management and Archiving</h3>
<p>The division within EMC that owns Documentum has changed their name from Content Management and Archiving to &#8220;Information Intelligence Group&#8221;. Not sure what this is about yet &#8211; I guess I&#8217;ll find out over the course of the conference. </p>
<h3>Momentum is Small This Year</h3>
<p>Momentum is the name of the old Documentum user group conference, and it&#8217;s also the name of EMC World&#8217;s &#8220;conference within a conference&#8221; that is focused on Documentum and the related content management technologies. </p>
<p>There are only 16 breakout sessions on Documentum today, and most are delivered by EMC product managers. Only three sessions today are being presented by customers. </p>
<p>The &#8220;Momentum Zone&#8221; at the solutions pavilion is tiny. There are probably less than 20 booths total, and only a handful of them are names I recognize from previous conferences. Blue Fish, Technology Services Group, and many other Documentum-focused partners that have had booths in the past elected not to exhibit this year. </p>
<h3>Missed The One Presentation I Wanted to See the Most</h3>
<p>I&#8217;m totally bummed out that I couldn&#8217;t get into John McCormack&#8217;s presentation on the Documentum roadmap. I guess I&#8217;m going to have to download the slides when they are available, but it&#8217;s not the same. </p>
<h3>Private Cloud</h3>
<p>From my perspective, EMC World is a conference about Documentum. Of course, that&#8217;s only one percent of what&#8217;s going on here, but it&#8217;s the one percent that I care about. But I listened to Joe Tucci&#8217;s keynote anyway to here his vision for the future of EMC. </p>
<p>EMC is pushing something they call the &#8220;Private Cloud&#8221;, EMC&#8217;s vision for operating a cloud model within your own data center. The idea is that with vmWare and other EMC technologies, you&#8217;ll be able to provision new computing services in your own datacenter in a manner similar to the way that Amazon, Google, Facebook, and other massive online companies do. Instead of having infrastructure dedicated to an application the way we do today, you&#8217;ll have a slew of generic computing resources (CPU, memory, bandwidth, and storage) that can seamlessly provision themselves as demand for them increases and then release resources into a common pool as demand falls off. </p>
<h3>CenterStage Update</h3>
<p>I attended Matt Coblenz&#8217;s presentation on CenterStage, EMC&#8217;s replacement for eroom. I had heard the CenterStage pitch in past years, and was excited to learn more about what exciting changes have been introduced over the past year. It turns out, not much is new. <a href="http://www.bluefishgroup.com/library/2009/centerstage-emcs-next-generation-collaboration-application/"><br />
CenterStage was a big topic at last year&#8217;s EMC World</a>, but it wasn&#8217;t officially released until about six months ago. As Matt presented some of his thoughts about the future, one of the audience members put him on the spot. </p>
<p>&#8220;Your product is nearly two years late, how can I trust your roadmap and vision?&#8221; the audience member asked. Matt  handled it as well as he could, saying, &#8220;You won&#8217;t until I earn your trust again. We haven&#8217;t done a good job of meeting commitments in the past, but we are trying harder.&#8221;</p>
<p>So the bottom line is that nothing much is new to report about CenterStage.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2010/emc-world-2010-day-one-initial-thoughts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Customizing the Web Publisher Rich Text Editor</title>
		<link>http://www.bluefishgroup.com/2010/wp-rich-text-editor/</link>
		<comments>http://www.bluefishgroup.com/2010/wp-rich-text-editor/#comments</comments>
		<pubDate>Fri, 16 Apr 2010 11:00:00 +0000</pubDate>
		<dc:creator>Lisa Hill</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Web Content Management]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=423</guid>
		<description><![CDATA[Introduction Recent releases of the EMC Documentum platform have offered web content authors alternatives to creating content via the traditional Web Publisher template editor. Despite the alternatives, we have found that the tried and true method of creating content via the forms based templates is still the most widely adopted (and really, most powerful). As [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Introduction</a><br />
    </h3>
<p>Recent releases of the EMC Documentum platform have offered web content authors alternatives to creating content via the traditional Web Publisher template editor.  Despite the alternatives, we have found that the tried and true method of creating content via the forms based templates is still the most widely adopted (and really, most powerful).  As part of the Web Publisher product, EMC provides a variety of content creation &#8220;widgets&#8221; that web developers assemble into these custom forms (called Rules Files) that content authors then use for content entry.  While each of these widgets is a valuable tool in the art of template design, there is one widget that stands heads and shoulders above the rest.  The content widget, colloquially referred to as the &#8220;Rich Text Editor&#8221;, allows content authors to contribute rich text (that is, text that contains images, links, and styling) to their web page.  This provides for flexibility and diversity in content that would be impossible to achieve with the other widgets alone.</p>
<p>This article will give a behind the scenes tour of the Web Publisher Rich Text Editor and will get you started with configuring and customizing it to meet the needs of your business.  It assumes that you have a working knowledge of Web Publisher and the content creation process using the template editor.  If you are new to Web Publisher, I&rsquo;d suggest reading this primer on <a href="/library/2005/web-publisher-template-basics/">Web Publisher Template Basics</a> first to give you the appropriate context.</p>
<h3>
        <a name="head2" class="section">What&#8217;s What</a><br />
    </h3>
<p>Unlike the other template editor widgets, the Web Publisher Rich Text Editor is not actually an EMC product at all, but is rather the embedded product called EditLive! developed by Ephox. Before diving any deeper, it is important to familiarize yourself with the key files that make up the Web Publisher template editor (including the Rich Text Editor):</p>
<ul>
<li>%appserver%/wp/webcomponent/library/contentxfer/<strong>swingTe.jar</strong><br />
            </p>
<p>					The swingTe.jar contains the implementation classes for all of the Web Publisher widgets, including the EditLiveWidget which embodies the Web Publisher Rich Text Editor.  The EditLiveWidget customizes the EditLive! component provided by Ephox to allow for Documentum specific repository interactions (for instance, browsing for links in the repository and importing images into the repository).
				</li>
<li>%appserver%/wp/webcomponent/library/contentxfer/<strong>editlivejava.jar</strong><br />
            </p>
<p>					The editlivejava.jar contains the implementation classes for the EditLive! directly as it is provided by Ephox.
				</li>
<li>%appserver%/wp/wp/editors/contenteditor/resources/<strong>EditorUI.properties</strong><br />
            </p>
<p>					The EditorUI.properties provides some configuration settings that drive the look and feel for the entire Web Publisher Template Editor.
				</li>
<li>%appserver%/wp/wp/editors/contenteditor/resources/<strong>editliveConfig.xml</strong><br />
            </p>
<p>					The editliveConfig.xml is the configuration file for the EditLive! editor itself.
				</li>
<li>%appserver%/wp/wp/library/ceedit/<strong>ceedit.jsp</strong><br />
            </p>
<p>					The ceedit.jsp generates the Web Publisher Editor applet.
				</li>
</ul>
<h3>
        <a name="head3" class="section">Configuration</a><br />
    </h3>
<p>As mentioned above, the editliveConfig.xml is the configuration file for the EditLive! editor &ndash; it drives all of the underlying configuration settings for the Rich Text Editor.  Many of the settings in this file are actually overwritten by settings specified in the Rules File definition of the editor instance.  For instance, you can specify in your rules file whether or not the &#8220;HTML&#8221; code tab is available (along with the default &#8220;Design&#8221; tab) with the parameters <code>htmlTextEdit="Y"</code> or <code>htmlTextEdit="N"</code>.</p>
<p>Some settings, however, are only configurable via this file.  Here are some of the most important configuration settings to be aware of in a Web Publisher implementation:</p>
<h4>Specifying Styles</h4>
<p>One of the biggest downsides to the forms based editing is that as users modify the content, what they are modifying does not look exactly like it will appear on the website (users have to WebView or Preview the content to see their modifications in context).  This is not that large of a concern when users are interacting with other widgets that collect specific pieces of information that the user knows are going to be formatted correctly by the site.  The Rich Text Editor, however, grants quite a bit more flexibility to the content author in how they author their content &ndash; and hence also requires from them more responsibility to format their content appropriately.</p>
<p>Wouldn&rsquo;t it be nice for content authors to get a better sense of how the content they are entering in the Rich Text Editor will look on the final web page directly as they are authoring it? The EditLive! widget actually allows for two mechanisms for including style information to drive the way the content is rendered in the Rich Text Editor itself &ndash; Importing a Stylesheet or Adding Inline Styles.</p>
<h3>Importing a Stylesheet</h3>
<p>Much as you would import a stylesheet for use on your rendered web page, the Ephox editor supports importing a stylesheet for use in the Rich Text Editor.  To do this, in the <code>&lt;head&gt;</code> of the editliveConfig.xml, simply add the stylesheet as a <code>&lt;link&gt;</code> element:</p>
<p>
        <code>&lt;link href="http://www.myserver.com/includes/css/base.css" rel="stylesheet" type="text/css"/&gt;</code>
    </p>
<p>If you are developing your site from scratch (or have the ability to undergo a refactoring of your site CSS), modularizing your CSS files such that the relevant styles for the body content of your page can be included in the Rich Text Editor could provide a greatly enhanced authoring experience without any extra work.   If you are not so lucky, however, your best bet would be to create an &#8220;editor environment&#8221; stylesheet specifically designed for the authoring experience that replicates the styles for your actual site CSS.</p>
<h3>Inline Styles</h3>
<p>Just as in your web page you always have the option to provide inline styles instead of relying on included CSS, so it is with the Rich Text Editor.  Inline styles can be especially useful when you just want to target a few styles to include in the content authoring experience.  For instance, let&rsquo;s say your authors are contributing content to a fixed width site.  The content that they are authoring always fits into a main content area that is 700px wide.  Wouldn&rsquo;t it be nice if the author could see where their content was going to wrap as they typed instead of having to preview first?  This is actually very easy to do &ndash; simply add this fixed body width as an inline style to the Rich Text Edtior by adding a <code>&lt;style&gt;</code> block to the head of the editliveConfig.xml:</p>
<pre>
        <code>
&lt;style type="text/css"&gt;
	body {width:700px;}
&lt;/style&gt;
					</code>
    </pre>
<div align="center">
        <img src="/article-assets/images/wprte-content-wrap.jpg" border="0" alt="Fig. 1: Web Publisher Rich Text Editor - Body Width Style Applied">
<p class="figure">
            <b><br />
              Figure 1:<br />
            </b> Web Publisher Rich Text Editor &#8211; Body Width Style Applied</p>
</p></div>
<h4>Modifying Copy/Paste Behavior</h4>
<p>Anyone performing a Web Content migration from a legacy system into Web Publisher will most likely find themselves spending quite a bit of time copy/pasting existing content into the Rich Text Editor.  There are 2 configuration settings that drive the behavior of how text is pasted into the editor &ndash; one that controls pastes from Microsoft Word, and one from existing websites.</p>
<p>The behavior when pasting in content from Word is governed by the configuration setting:</p>
<p>
        <code>&lt;wordImport styleOption="[specify value here]"/&gt;</code>
    </p>
<p>And behavior when pasting in HTML content from an existing web page is governed by the configuration setting:</p>
<p>
        <code>&lt;htmlImport styleOption="[specify value here]"/&gt;</code>
    </p>
<p>The following values are supported:</p>
<ul>
<li>
            <i>user_prompt</i> &#8211; Users will be prompted as to whether they wish to import the existing styles as inline or embedded styles or strip them from the imported text.</li>
<li>
            <i>merge_embedded_styles</i> &#8211; This setting will result in EditLive! importing styles from the selected content with the styles stored in the <code>&lt;head&gt;</code> of the document and class attributes will be applied where relevant.</li>
<li>
            <i>merge_inline_style</i> &#8211; This setting will result in EditLive! importing styles from the selected content with style information applied inline in place of class attributes.</li>
<li>
            <i>clean</i> &#8211; The clean setting will result in EditLive! stripping the styles from the imported text and only structural HTML elements will be imported, this includes &lt;b&gt;, &lt;p&gt; etc.</li>
<li>
            <i>plain_text</i> &#8211; The plain_text setting will strip out all style information from the imported text.</li>
</ul>
<div class="callout">
<p>
            <b></b>
        </p>
<p>
            <strong>Note:</strong>In Web Publisher 6.5sp2, the htmlImport configuration is missing from the OOB edlitliveConfig.xml &ndash; and with it missing, the behavior is defaulting to pasting in all of the style information inline.  Most modern websites don&rsquo;t leverage inline styles as a rule, but instead use CSS to drive site behavior.  For this reason, we highly recommend that you consider adding this configuration option with it set to &#8220;clean&#8221;.  This will give you the same underlying HTML structure as your existing site without polluting your markup with a bunch of erroneous style information.</p>
</p></div>
<h4>Modifying the Spell Checker</h4>
<p>One helpful feature of the Rich Text Editor is the built in &#8220;spell checker&#8221;.  Web Publisher installs with a set of dictionaries provided by Ephox.  A copy of the spell checker&#8217;s dictionary/word list is maintained on the server and is downloaded to the client machine on its first use of EditLive! and it is cached there. This ensures responsiveness and does not require content to be sent to the server for spell checking.</p>
<h3>Adding New Locale Definitions</h3>
<p>When a content author modifies a piece of content, the correct dictionary is automatically used, based upon the locale of the document being modified.  The list of which dictionary to use for which locale is specified in the editliveConfig.xml.  If you add a new locale to Web Publisher, there is a very good chance you will need to update the EditLive! configuration to know about it as well.  In an OOB Web Publisher installation, the following locales are pre-defined:</p>
<pre>
        <code>
&lt;dictionary&gt;
   &lt;!--default dictionary to use when object has no locale--&gt;
   &lt;default&gt;/wp/editors/contenteditor/dictionary/en_us_4_0.jar&lt;/default&gt;
   &lt;!-- English US--&gt;
   &lt;en_US&gt;/wp/editors/contenteditor/dictionary/en_us_4_0.jar&lt;/en_US&gt;
   &lt;!-- English UK --&gt;
   &lt;en_GB&gt;/wp/editors/contenteditor/dictionary/en_br_4_0.jar&lt;/en_GB&gt;
   &lt;!-- Danish --&gt;
   &lt;da_DK&gt;/wp/editors/contenteditor/dictionary/da_4_0.jar&lt;/da_DK&gt;
   &lt;!-- Dutch --&gt;
   &lt;nl_NL&gt;/wp/editors/contenteditor/dictionary/du_4_0.jar&lt;/nl_NL&gt;
   &lt;!-- Finnish --&gt;
   &lt;fi_FI&gt;/wp/editors/contenteditor/dictionary/fi_4_0.jar&lt;/fi_FI&gt;
   &lt;!--French - European and Canadian --&gt;
   &lt;fr_CA&gt;/wp/editors/contenteditor/dictionary/fr_4_0.jar&lt;/fr_CA&gt;
   &lt;fr_FR&gt;/wp/editors/contenteditor/dictionary/fr_4_0.jar&lt;/fr_FR&gt;
   &lt;!-- German --&gt;
   &lt;de_DE&gt;/wp/editors/contenteditor/dictionary/ge_4_0.jar&lt;/de_DE&gt;
   &lt;!-- Italian --&gt;
   &lt;it_IT&gt;/wp/editors/contenteditor/dictionary/it_4_0.jar&lt;/it_IT&gt;
   &lt;!-- Norwegian --&gt;
   &lt;no_NO&gt;/wp/editors/contenteditor/dictionary/no_4_0.jar&lt;/no_NO&gt;
   &lt;!--Portuguese (Iberian) --&gt;
   &lt;pt_PT&gt;/wp/editors/contenteditor/dictionary/po_4_0.jar&lt;/pt_PT&gt;
   &lt;!--Spanish - European, Mexican and South American--&gt;
   &lt;es_ES&gt;/wp/editors/contenteditor/dictionary/sp_4_0.jar&lt;/es_ES&gt;
   &lt;!--Swedish--&gt;
   &lt;sv_SE&gt;/wp/editors/contenteditor/dictionary/sw_4_0.jar&lt;/sv_SE&gt;
&lt;/dictionary&gt;
					</code>
    </pre>
<p>To add a new locale, simply add the relevant element to the editliveConfig.xml and specify the desired dictionary to use.</p>
<h3>Customizing a Dictionary</h3>
<p>While the dictionary provided OOB is very good, nearly every organization has its own set of common words &ndash; perhaps the name of the organization, a product name, or other industry-specific terms that will show up as &#8220;misspelled&#8221; in the Rich Text Editor.  Individual users of course always have the option to update the local copy of their dictionary via the &#8220;Add&#8221; feature of the spell checker (similar to the spell checker &#8220;Add&#8221; feature in Microsoft Word, this will update the cached dictionary on the user&rsquo;s local machine).  Since these are words that are really organizational in nature, however, wouldn&rsquo;t it be great if you could just push these updates to all of the content authors?  Well, it turns out you can!  By using an existing dictionary as a starting point, you can create your own custom dictionary for use by your content authors:</p>
<ol>
<li>Unzip the dictionary you want to modify (found in %appserver%/wp/wp/editors/contenteditor/dictionary) to a temporary location.  For example, to create your custom dictionary based on the US English dictionary, unzip the file en_us_4_0.jar.  You will find in the location where you unzipped this the following files: 
<ul>
<li>accent.tlx</li>
<li>correct.tlx</li>
<li>dictionary2.clx</li>
<li>dictionary.tlx</li>
</ul>
</li>
<li>In the directory with this unzipped files, using Notepad (or your favorite plain text editor) create a plain text file called customdictionary.tlx.
<ul>
<li>At the top of this file add the line: <code>#LID 24941</code>
                </li>
<li>For each word that you want to add to the dictionary, add the word on its own line in the file, then one &#8220;tab space&#8221; from the word, add the letter &#8220;i&#8221;.  For instance, if you wanted to add the words WebPublisher and Ehpox to your custom dictionary, your customdictionary.tlx file would look like:
<pre>
                        <code>
#LID 24941
WebPublisher	i
Ephox	i
								</code>
                    </pre>
</li>
</ul>
</li>
<li>From within the temporary directory that contains these dictionary files, using the Java jar command, create a new jar file that packages your new file with the four files that came from the OOB dictionary.  For instance, if you have java installed in C:Java, you would run the command:
<p>            <code>C:Javabinjar cvf customdictionary.jar .</code>
        </li>
<li>Place your customdictionary.jar file in the same %appserver%/wp/wp/editors/contentedtior/dictionary directory with the OOB dictionaries.</li>
<li>Update the appropriate locale(s) in the editliveConfig.xml to use your new custom dictionary.</li>
</ol>
<p>EditLive! will automatically detect this change in the server-side dictionary and will update the cached version on any client machines the next time they load them.</p>
<div class="callout">
<p>
            <b></b>
        </p>
<p>
            <strong>HINT:</strong> Intead of making changes directly in the editliveConfig.xml or the EditorUI.properties, we suggest that within your webapp&rsquo;s &#8220;custom&#8221; directory you add a /editors/contenteditor/resources folder and place copies of the files in that directory.  To get the Template Editor to pick up the changes, simply open your java console, hit &#8220;x&#8221; to dump the classloader, and re-open the template editor in your browser.  No need to bounce the application server, and no need to even restart your browser!</p>
</p></div>
<h3>
        <a name="head4" class="section">Customization</a><br />
    </h3>
<p>Configuration can obviously only take you as far as the product has been designed to take you.  Sometimes that just isn&rsquo;t far enough and you need to customize the existing functionality.  Here are two strategies for customizing the Rich Text Editor behavior:</p>
<h4>Adding a Custom Toolbar Button</h4>
<p>The Rich Text Editor provided with Web Publisher includes a variety of &#8220;toolbar buttons&#8221; that drive user interaction with the content.  For instance, there are toolbar buttons for inserting images, hyperlinks, tables, bulleted lists, and so on.  Which toolbars show up in the editor depends not only on the configuration setting in the editliveConfig.xml, but also which have been configured in the rules file for the current template.  You are not limited, however, to the toolbar buttons provided in the OOB implementation &ndash; the editor actually has built in support for adding custom toolbar buttons.</p>
<p>Let&rsquo;s take a very simple use case &ndash; let&rsquo;s say that you want your content authors to be able to add a disclaimer (which is really just a simple HTML fragment) anywhere in their content in an ad-hoc manner.  Since they do this often, you don&rsquo;t want them to have to bother typing it out every time.  You can add a toolbar button that inserts the disclaimer into the content area for them. All you have to do is:</p>
<ol>
<li>Create a 16x16px toolbar icon &ndash; this icon is required for the imageURL attribute of your custom toolbar definition.  (Hint: This image needs to be saved in .gif format &ndash; if you create a .jpg it won&rsquo;t work.  Don&rsquo;t shoot the messenger.).</li>
<li>Add the toolbar definition to the editliveConfig.xml where you would like it to appear in the toolbar.  For instance, if you wanted to add the new toolbar button between the &#8220;Insert Symbol&#8221; and &#8220;Insert Bookmark&#8221; functions, you would modify the file to read:
<pre>
                <code>
&lt;toolbarSeparator/&gt;
	&lt;toolbarButton name="tlbHRule"/&gt;
	&lt;toolbarButton name="tlbHLink"/&gt;
        &lt;toolbarButton name="tlbSymbol"/&gt;
        &lt;customToolbarButton name="customInsertDisclaimer" text="Insert Disclaimer" imageURL="http://www.myserver.com/images/my16x16icon.gif" action="insertHTMLAtCursor" value="%3Cp%3EThis%20is%20my%20disclaimer%3C%2Fp%3E" /&gt;
        &lt;toolbarButton name="tlbBookmark"/&gt;
        &lt;toolbarButton name="tlbImageServer"/&gt;
&lt;toolbarSeparator/&gt;
						</code>
            </pre>
<p>					Note that the value attribute that you specify for the customToolbarButton (the text that is actually inserted into the content area) must be URL encoded.
					</li>
<li>Include the unique name of your toolbar in your rules file definition.  For instance, for this example you would add to the content rule:
<p>            <code>customInsertText=&rdquo;Y&rdquo;</code>
        </li>
</ol>
<p>Voila!  You now have a custom toolbar button added to the Rich Text Editor.  When you click on the button, the disclaimer paragraph will be added to the content editor output.</p>
<div align="center">
        <img src="/article-assets/images/wprte-custom-button.jpg" border="0" alt="Fig. 2: Web Publisher Rich Text Editor - Custom Toolbar Button">
<p class="figure">
            <b><br />
              Figure 2:<br />
            </b> Web Publisher Rich Text Editor &#8211; Custom Toolbar Button</p>
</p></div>
<h4>Extending the EditLiveWidget</h4>
<p>What if none of the configuration and customization hooks we have described thus far provide the flexibility you need, what if you simply need to add custom business logic to the RichText Editor?  For instance, we recently had a client that wanted to add logic that determined which users should have access to the &#8220;HTML&#8221; (or code view) tab.  What are your options then?</p>
<p>At this point you are going to need to step into the world of custom development and extend the EditLiveWidget itself.  Here are a couple of pointers for successfully extending the EditLiveWidget:</p>
<ul>
<li>As mentioned above, the ceedit.jsp generates the Web Publisher Editor applet.  It is in this file that you will need to add your custom .jar&rsquo;s to make them available to the template editor (just as you would if you were creating your own custom widget from scratch).  It is also in this file that many parameters are defined and passed to the applet.  You can add your own custom parameters here (populated with whatever logic necessary based upon the user, repository, content, etc) and they will be available in your custom widget.</li>
<li>You may have created your own custom widgets in the past, and had been able to simply package them in a jar and add them to the ceedit.jsp class definition and had no problems.  When extending the EditLiveWidget, however, this won&rsquo;t be good enough and you will need to sign your applet jar.  It appears that EditLive! uses some system resources that cause security exceptions if your jar is not signed properly.  In fact, when customizing certain releases we&rsquo;ve found that signing our own jar was not sufficient and we needed to sign the swingTe.jar and edlitlivejava.jar as well.</li>
</ul>
<h3>
        <a name="head5" class="section">Other Tips &amp; Tricks</a><br />
    </h3>
<h4>Hey &ndash; I want that feature!</h4>
<p>Since EditLive! is a true enterprise product of its own right, it is continually being improved and upgraded.  With nearly each new release of Web Publisher a new version of the EditLive! editor is included. While upgrading the Documentum stack to support a new version of Web Publisher can be a large undertaking (particularly if you have a bunch of WDK customizations), it actually is quite straight forward to &#8220;upgrade&#8221; the template editor functionality.  All you need to do is replace the swingTe.jar and the editlivejava.jar from your current Web Publisher installation with those from your &#8220;desired&#8221; release.  Depending on what releases you are upgrading from and to, you may also need to update the &lt;ephoxLicenses&gt; section of the editliveConfig.xml file with the relevant license information from your target release.</p>
<pre>
        <code>
&lt;ephoxLicenses&gt;
       &lt;license
            accountID="123456789100"
            activationURL="http://www.ephox.com/&hellip;"
            domain="DOCUMENTUM"
            expiration="NEVER"
            forceActive="false"
            key="8FFF-FFFF-FFFF-FFFF"
            eqEditor="false"
            licensee="DOCUMENTUM"
            product="EditLive for Java"
            release="6.0"
       /&gt;
&lt;/ephoxLicenses&gt;
				</code>
    </pre>
<div class="callout">
<p>
            <b></b>
        </p>
<p>
            <strong>Note:</strong> While this technique can most obviously be used to upgrade the template editor &amp; rich text editor to a newer version, it can also be used in reverse (i.e., to downgrade to a previously released version).  We had many clients that needed to do this while on the 5.3 stack, as the 5.3sp2 release of the rich text editor in particular had fewer problems with images in the rich text editor than some of the later service packs.  For those that are still on 5.3, however, I have some good news.  It appears that the Rich Text Editor in the 6.5sp2 release has none of these prior &#8220;quirks&#8221; and is a release worthy of an upgrade.</p>
</p></div>
<h4>I tried that, but it didn&rsquo;t work &ndash; HELP!</h4>
<p>Well let&rsquo;s see, we have a WDK application invoking a custom applet that relies on a template specific rules file and then leverages a third party developed application, which reads its own set of configuration data, all to present the user with a swing application &ndash; what could go wrong?  Obviously there are a lot of moving parts here, and sometimes to figure out what is going on, tracing will become your best friend.</p>
<p>Here are some of the most useful of the Web Publisher tracing options:</p>
<ul>
<li>%APPSERVER%/wp/WEB-INF/classes/<strong>WcmTraceProp.properties</strong>
<ul>
<li>WCMSESSIONENABLEDBYDEFAULT &ndash; This value must be set to true to enable any Server or Client side tracing</li>
</ul>
</li>
<li>%APPSERVER%/wp/WEB-INF/classes/com/documentum/contenteditor/resources/<strong>EditorServerTraceProp.properties</strong>
<ul>
<li>EDITORSERVER &ndash; Traces the Server side of the editor (lookup of the Web Publisher Editor, parser errors, validation &amp; entity resolution, double-byte character encoding exceptions &amp; checksum errors)</li>
<li>CONTENTIF &ndash; Traces editor operations (export path, export errors, and XML file encoding)</li>
</ul>
</li>
</ul>
<p>The location of the generated log files will vary by installation, but can be specified in the log4j.properties that is located in your %APPSERVER%/wp/WEB-INF/classes/log4j.properties.</p>
<p>To trace the template editor itself, you will need to not only turn on the tracing flag:</p>
<ul>
<li>%APPSERVER%/wp/wp/editors/contenteditor/resources/<strong>EditorUI.properties</strong>
<ul>
<li>contenteditor.showDebugButton &ndash; adds a &#8220;Debug&#8221; button to the template editor for viewing debug information from the template editor</li>
<li>editlive.debug &ndash; turns on tracing for the EditLive! This tracing can be viewed in the applet Java console</li>
</ul>
</li>
</ul>
<div class="callout">
<p>
            <b></b>
        </p>
<p>
            <strong>Note:</strong> Web Publisher tracing options can also be turned for the current session by visiting: http://%webpublisherserver%/wp/wp/app/tracing.jsp and checking the relevant checkboxes.</p>
</p></div>
<h3>
        <a name="head6" class="section">Resources</a><br />
    </h3>
<p>The following links and documents were referenced in writing this article, and are a great source for more information on all of the topics above:</p>
<ul>
<li>EditLive! Java Developers Guide: <a target="_blank" href="http://www.ephox.com/developers/editliveforjava/v40/html/">http://www.ephox.com/developers/editliveforjava/v40/html/</a>
        </li>
<li>EditLive! Configuration File Specification: <a target="_blank" href="http://liveworks.ephox.com/documentation/editlive/v60/RefHTML/index.html?configuration_file_element.htm">http://liveworks.ephox.com/documentation/editlive/v60/RefHTML/index.html?configuration_file_element.htm</a>
        </li>
<li>EditLive! Hints &amp; Tips: <a target="_blank" href="http://liveworks.ephox.com/hints-tips">http://liveworks.ephox.com/hints-tips</a>
        </li>
<li>Web Publisher Developer&#8217;s Guide <a target="_blank" href="http://powerlink.emc.com">http://powerlink.emc.com</a>
        </li>
</ul>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2010/wp-rich-text-editor/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>New Article: Customizing the Web Publisher Rich Text Editor</title>
		<link>http://www.bluefishgroup.com/2010/new-article-customizing-the-web-publisher-rich-text-editor/</link>
		<comments>http://www.bluefishgroup.com/2010/new-article-customizing-the-web-publisher-rich-text-editor/#comments</comments>
		<pubDate>Thu, 15 Apr 2010 21:29:25 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=424</guid>
		<description><![CDATA[Lisa Hill has just published a great article on how to customize the Rich Text Editor in Documentum Web Publisher. The Rich Text Editor is the WYSIWYG editor that is used by web page authors and editors to create content for web sites being managed by Documentum. The editor functions like Microsoft Word and lets [...]]]></description>
				<content:encoded><![CDATA[<p>Lisa Hill has just published a great article on <a href="/library/2010/wp-rich-text-editor/">how to customize the Rich Text Editor in Documentum Web Publisher</a>. The Rich Text Editor is the WYSIWYG editor that is used by web page authors and editors to create content for web sites being managed by Documentum. The editor functions like Microsoft Word and lets you style your text (bold, underline, etc.), add tables, create bulleted lists and things like that.</p>
<p>From time to time, we get requests from our clients to customize this editor. Some want us to add extra toolbar buttons that provide some custom capability. Others want us to make the style of the editor match the style of their web site to give an even better preview of what the content will look like. </p>
<p>Lisa&#8217;s article shows how to do all of these things and provides some great tips on how to debug and troubleshoot your customizations. If you are thinking of modifying the Web Publisher Rich Text Editor, this article is a must read.</p>
<p>Read <a href="/library/2010/wp-rich-text-editor/">Customizing the Web Publisher Rich Text Editor</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2010/new-article-customizing-the-web-publisher-rich-text-editor/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New Article: Making Alfresco Share Dashlets Configurable</title>
		<link>http://www.bluefishgroup.com/2010/new-article-making-alfresco-share-dashlets-configurable/</link>
		<comments>http://www.bluefishgroup.com/2010/new-article-making-alfresco-share-dashlets-configurable/#comments</comments>
		<pubDate>Wed, 07 Apr 2010 00:38:35 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=422</guid>
		<description><![CDATA[Josh McJilton, one of the Project Managers here at Blue Fish, has just written an article on how to make Dashlets in Alfresco Share configurable. Dashlets are like portlets or widgets that users can include on various pages in Alfresco Share (Alfresco&#8217;s collaboration system). Typical dashlets might be document-oriented (like showing a real-time list of [...]]]></description>
				<content:encoded><![CDATA[<p>Josh McJilton, one of the Project Managers here at Blue Fish, has just written an article on <a href="/library/2010/making-alfresco-share-dashlets-configurable/">how to make Dashlets in Alfresco Share configurable</a>. Dashlets are like portlets or widgets that users can include on various pages in Alfresco Share (Alfresco&#8217;s collaboration system). Typical dashlets might be document-oriented (like showing a real-time list of changes to your team&#8217;s documents) or they might pull data from some external system (like showing the weather in your favorite city). </p>
<p>To be useful, most dashlets neet to be configurable by the end user. For example, you might want to select which team&#8217;s documents to monitor or which city&#8217;s weather to display. Dashlets themselves are pretty easy to create (it only takes a little JavaScript and some XML files), but if you want your dashlet to be configurable, it can get a little tricky. </p>
<p>Josh explains it all in <a href="/library/2010/making-alfresco-share-dashlets-configurable/">Making Alfresco Share Dashlets Configurable</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2010/new-article-making-alfresco-share-dashlets-configurable/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Making Alfresco Share Dashlets Configurable</title>
		<link>http://www.bluefishgroup.com/2010/making-alfresco-share-dashlets-configurable/</link>
		<comments>http://www.bluefishgroup.com/2010/making-alfresco-share-dashlets-configurable/#comments</comments>
		<pubDate>Tue, 06 Apr 2010 11:00:00 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Custom ECM Solutions]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=421</guid>
		<description><![CDATA[Introduction Note: This article isn&#8217;t an exhaustive dashlet development how-to. For an introduction to the platform and technologies used to build dashlets, a great place to start is the Alfresco Surf Platform Developers Guide. Dashlets are a lot of fun. They expose a tremendous amount of functionality, and they give users and project teams the [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Introduction</a><br />
    </h3>
<p class="note">
        <b>Note: </b>This article isn&#8217;t an exhaustive dashlet development how-to. For an introduction to the platform and technologies used to build dashlets, a great place to start is the <a target="_blank" href="http://wiki.alfresco.com/wiki/Surf_Platform_-_Developers_Guide">Alfresco Surf Platform Developers Guide</a>.</p>
<p>Dashlets are a lot of fun. They expose a tremendous amount of functionality, and they give users and project teams the power to assemble and organize that functionality as they see fit. They can be as simple as the two file Hello World dashlet from <a target="_blank" href="http://drquyong.com/myblog/?p=25">Dr. Q&#8217;s Workshop</a>. On the other hand, they can also be incredibly complex, with well over 20 files making up a single dashlet.</p>
<p>I know that when I first waded into the deep end of the dashlet pond, I started drowning quite quickly. Back when I was a naive &#8216;noob&#8217;, it took me a while to find my way around and comfortably accomplish some of the tasks I had assumed would be very easy. One of the areas I struggled with was figuring out how to make my dashlets configurable, so that end users could change the way they look or behave. I wanted to make dashlets similar to Alfresco&#8217;s Web View dashlet that lets users provide a URL, and then displays the page referenced by that URL within the dashlet.</p>
<div align="center">
        <img src="/article-assets/images/alfresco-dashlet-configuration/web-view-dashlet.png" border="0" alt="Fig. 1: Unconfigured instace of the Alfresco Web View dashlet.">
<p class="figure">
            <b><br />
              Figure 1:<br />
            </b> Unconfigured instace of the Alfresco Web View dashlet.</p>
</p></div>
<p>The goal of this article is to help you understand how to make your dashlets configurable so that you can focus on the development of new features, and not the plumbing of configuration values.</p>
<h3>
        <a name="head2" class="section">Dashlets Are Easy, Sometimes</a><br />
    </h3>
<p>Dashlets can be very simple. For example, a simple Hello World dashlet can be implemented with just two files:</p>
<p>    <code>helloworld.get.desc.xml</code>:
<pre>
        <code>&lt;webscript&gt;
  &lt;shortname&gt;Hello World&lt;/shortname&gt;
  &lt;description&gt;Hello World Dashlet&lt;/description&gt;
  &lt;family&gt;dashlet&lt;/family&gt;
  &lt;url&gt;/components/dashlets/helloworld&lt;/url&gt;
&lt;/webscript&gt;
</code>
    </pre>
<p>    <code>helloworld.get.html.ftl</code>:
<pre>
        <code>&lt;div class="dashlet"&gt;
  &lt;div class="title"&gt;Hello World&lt;/div&gt;
  &lt;div class="body"&gt;
    &lt;span&gt;Hello World&lt;/span&gt;
  &lt;/div&gt;
&lt;/div&gt;</code>
    </pre>
<p>Drop these two files into the <code>shareWEB-INFclassesalfrescosite-webscriptsorgalfrescocomponentsdashlets</code> directory and you&#8217;ve got a new dashlet ready to go.</p>
<p>If some dashlets can be so simple, why are others often so hard? Well, in this article I&#8217;m going to show you how taking this simple, static Hello World dashlet, and adding configuration capabilities expands these two source files into a total of <strong>16</strong> files. I know, I know; that sounds like a lot. But once you learn your way around you&#8217;ll be adding configuration capabilities to all you dashlets.</p>
<h3>
        <a name="head3" class="section">A Configurable Example</a><br />
    </h3>
<p>For the purposes of this article, I&#8217;ll be using an example dashlet that accepts and displays three configuration values. Not earth shattering functionality, but then very few people would have guessed Twitter was going to change the world when it was first rolled out. Here is a look at the end product in action:</p>
<div align="center">
        <img src="/article-assets/images/alfresco-dashlet-configuration/example-dashlet-unconfigured.png" border="0" alt="Fig. 2: Unconfigured instace of our example dashlet.">
<p class="figure">
            <b><br />
              Figure 2:<br />
            </b> Unconfigured instace of our example dashlet.</p>
</p></div>
<p>This dashlet allows users to dynamically configure its three displays values. As you can see below, it accepts a title, headline, and story:</p>
<div align="center">
        <img src="/article-assets/images/alfresco-dashlet-configuration/example-dashlet-config-dialog.png" border="0" alt="Fig. 3: Configuration dialog for our example dashlet.">
<p class="figure">
            <b><br />
              Figure 3:<br />
            </b> Configuration dialog for our example dashlet.</p>
</p></div>
<p>Once the configuration dialog is saved the dashlet on the dashboard is automatically updated with the new values, and those values are persisted for all future views of that instance of the dashlet.</p>
<div align="center">
        <img src="/article-assets/images/alfresco-dashlet-configuration/example-dashlet-configured.png" border="0" alt="Fig. 4: Configured instace of our example dashlet.">
<p class="figure">
            <b><br />
              Figure 4:<br />
            </b> Configured instace of our example dashlet.</p>
</p></div>
<h3>
        <a name="head4" class="section">Anatomy of a Dashlet&#8217;s Configuration Process</a><br />
    </h3>
<p>As you begin experimenting with dashlet development, I highly recommend that you check out the Alfresco Developers Wiki. This site has some <a target="_blank" href="http://wiki.alfresco.com/wiki/3.0_Web_Scripts_Framework">tremendously useful Web Scripts framework documentation and examples</a>. One particularly helpful section discusses the framework&#8217;s use of the MVC pattern, and how a Web Script&#8217;s execution flows through the framework. In that section the following diagram is used to help explain the flow:</p>
<div align="center">
        <img src="/article-assets/images/alfresco-dashlet-configuration/WebOrientedRestStyleArchitecture.jpg" border="0" alt="Fig. 5: (from http://wiki.alfresco.com/wiki/Image:WebOrientedRestStyleArchitecture.jpg) ">
<p class="figure">
            <b><br />
              Figure 5:<br />
            </b> (from http://wiki.alfresco.com/wiki/Image:WebOrientedRestStyleArchitecture.jpg)</p>
</p></div>
<p>Our example dashlet will actually complete this loop three different times as we interact with it. Let&#8217;s quickly review each of the three loops.</p>
<h4>Main Dashlet Display</h4>
<p>The initial loop is completed every time our dashlet is drawn onto a dashboard. In this loop, the steps highlighted in the diagram execute as follow:</p>
<ol>
<li>The dashboard includes the dashlet and makes a call to the Web Script Runtime using the dashlet&#8217;s URL.</li>
<li>
            <code>aafb.get.desc.xml</code> &#8211; The Web Script Runtime finds the appropriate Web Script as defined in the <code>aafb.get.desc.xml</code> then hands off to the controller for execution.</li>
<li>
            <code>aafb.get.js / aafb.get.config.xml</code> &#8211; The JavaScript controller (<code>aafb.get.js</code>) executes, using the configuration values in the config xml (<code>aafb.get.config.xml</code>) as necessary.</li>
<li>
            <code>aafb.get.head.ftl / aafb.get.html.ftl / aafb.get.properties</code> &#8211; The view uses values set on the model by the controller and properties from the <code>aafb.get.properties</code> to assemble and render a response with the FreeMarker templates defined in <code>aafb.get.head.ftl</code> and <code>aafb.get.html.ftl</code>.</li>
<li>The Web Script Runtime sends the results back using the appropriate protocol.</li>
<li>The Web Script client receives the response in the requested format.  In this case, that format is HTML.</li>
</ol>
<h4>Configuration Dialog Display</h4>
<p>The second loop is completed when users click on the dashlet&#8217;s Configure link. In this loop, the steps highlighted in the diagram execute as follow:</p>
<ol>
<li>
            <code>aafb.js</code> &#8211; The <code>onConfigAafbClick</code> method defined in the <code>aafb.js</code> is called when a user click the Config link, and this initiates a request to the Web Script Runtime.</li>
<li>
            <code>config-aafb.get.desc.xml</code> &#8211; The Web Script Runtime finds the appropriate Web Script as defined in the <code>config-aafb.get.desc.xml</code> then hands off to the controller for execution.</li>
<li>No controller logic is necessary to render the dialog, so control passes straight to the view.</li>
<li>
            <code>config-aafb.get.head.ftl / config-aafb.get.properties</code> &#8211; The view uses properties from the <code>config-aafb.get.properties</code> to assemble and render a response using the FreeMarker template defined in <code>config-aafb.get.html.ftl</code>.</li>
<li>The Web Script Runtime sends the results back using the appropriate protocol.</li>
<li>The Web Script client receives the response in the requested format.  In this case, that format is HTML.</li>
</ol>
<h4>Configuration Dialog Processing</h4>
<p>The final loop is completed when a user submits the configuration dialog by clicking the OK button. In this loop, the steps highlighted in the diagram execute as follow:</p>
<ol>
<li>The Web Script Runtime is called a third time when a user submits the configuration dialog.</li>
<li>
            <code>config-aafb.post.desc.xml</code> &#8211; The Web Script Runtime finds the appropriate Web Script as defined in the <code>config-aafb.post.desc.xml</code> then hands off to the controller for execution.</li>
<li>
            <code>config-aafb.post.json.js</code> &#8211; The JavaScript controller (<code>config-aafb.post.json.js</code>) executes.</li>
<li>
            <code>config-aafb.post.json.ftl / config-aafb.post.properties</code> &#8211; The view uses values set on the model by the controller and properties from the <code>config-aafb.post.properties</code> to assemble and render a response using the FreeMarker template defined in <code>config-aafb.post.json.ftl</code>.</li>
<li>The Web Script Runtime sends the results back using the appropriate protocol.</li>
<li>The Web Script client receives the response in the requested format.  In this case, that format is JSON.</li>
</ol>
<h3>
        <a name="head5" class="section">A Closer Look</a><br />
    </h3>
<p>First, let&#8217;s look at where the 16 files that make up this dashlet live within the context of the Share application. Here is a view of the files that make up our example dashlet deployed into Alfresco Enterprise 3.2r:</p>
<div align="center">
        <img src="/article-assets/images/alfresco-dashlet-configuration/dashlet-xray-combined.png" border="0" alt="Fig. 6: Deployed view of all the files that make up our example dashlet.">
<p class="figure">
            <b><br />
              Figure 6:<br />
            </b> Deployed view of all the files that make up our example dashlet.</p>
</p></div>
<p>If this looks a little foreign to you, then let me direct you over to a great article about <a href="/library/2010/painless-alfresco-development-source-code-organization/">Alfresco source code organization</a> written by my colleague Josh Toub.</p>
<p>These 16 files require 9 easy steps to enable our configuration functionality. Let&#8217;s dive right in.</p>
<h4>Define Defaults</h4>
<p>The first thing we need to do is define some default values for our configuration parameters. These default values will be used when the dashlet is first instantiated onto the dashboard. Default values are defined in the <code>aafb.get.config.xml</code> file as follows:</p>
<pre>
        <code>&lt;aafb&gt;
  &lt;title&gt;Configurable Dashlet Title&lt;/title&gt;
  &lt;headline&gt;Configure your headline&lt;/headline&gt;
  &lt;story&gt;Tell a story, but make it short!&lt;/story&gt;
&lt;/aafb&gt;</code>
    </pre>
<h4>Set Configuration Parameter Values</h4>
<p>Next, we need to tell our JavaScript controller how to handle our configuration parameters and where to look for defaults. This is all done in the <code>aafb.get.js</code> file as follows:</p>
<pre>
        <code>function main()
{
  var title = args.title;
  var headline = args.headline;
  var story = args.story;
  
  // Create XML object to pull values from
  // configuration file
  var conf = new XML(config.script);

  // Use the defaults from the XML configuration file
  // (aafb.get.config.xml) if no values in args array
  if (!title)
  {
    title = conf.title[0].toString();
  }

  if (!headline) 
  {
    headline = conf.headline[0].toString();
  }

  if (!story) 
  {
    story = conf.story[0].toString();
  }
  
  // Set values on the model for use in templates
  model.title = title;
  model.headline = headline;
  model.story = story;
}

main();</code>
    </pre>
<h4>Layout/Use Configuration Values on Dashlet Display</h4>
<p>Now that we&#8217;ve got some configuration values defined, we need to display them within our dashlet. We define the dashlet&#8217;s layout with a FreeMarker template in the <code>aafb.get.html.ftl</code> file as follows:</p>
<pre>
        <code>&lt;script type="text/javascript"&gt;//&lt; ! [CDATA[
  new Alfresco.Aafb("${args.htmlid}").setOptions(
  {
    "componentId": "${instance.object.id}",
    "titleStr": "${title}",
    "headlineStr": "${headline}",
    "storyStr": "${story}"
  });
  new Alfresco.widget.DashletResizer("${args.htmlid}", "${instance.object.id}");
//] ] &gt;&lt;/script&gt;

&lt;div class="dashlet aafb"&gt;
  
  &lt;div id="${args.htmlid}-title" class="title"&gt;
    ${title}
  &lt;/div&gt;

  &lt;div class="toolbar"&gt;
    &lt;a id="${args.htmlid}-configAafb-link" class="configure theme-color-1" href="#"&gt;${msg("config")}&lt;/a&gt;
  &lt;/div&gt;
  
  &lt;div class="body scrollableList"&gt;
    &lt;h2&gt;&lt;span id="${args.htmlid}-headline"&gt;${headline}&lt;/span&gt;&lt;/h2&gt;
    &lt;p&gt;&lt;span id="${args.htmlid}-story"&gt;${story}&lt;/span&gt;&lt;/p&gt;
  &lt;/div&gt;

&lt;/div&gt;</code>
    </pre>
<p>This template uses properties values from the <code>aafb.get.properties</code> file and has access to the scripts included in the <code>aafb.get.head.ftl</code> file.</p>
<h4>Create Instance of Custom Object for Managing Configuration</h4>
<p>At the top of our <code>aafb.get.html.ftl</code> you probably noticed a script block. The first seven lines within that block create a new instance of a custom object. This custom object is used to manage the values of our configuration parameters and control the behavior of the configuration dialog used to set those values.</p>
<p>When the script block executes on the loading of our dashlet, the constructor and <code>setOptions</code> methods of our custom object are called. Those methods are defined in the <code>aafb.js</code> file. The code snippet below provides the entire contents of the <code>aafb.js</code> so that you can see how these two methods fit into the overall file. We&#8217;ll discuss the individual sections of the file a little bit later.</p>
<pre>
        <code>/**
 * Alfresco.Aafb
 *
 */
(function()
{
  /**
   * YUI Library aliases
   */
  var Dom = YAHOO.util.Dom,
      Event = YAHOO.util.Event;

  /**
   * Alfresco Slingshot aliases
   */
  var $html = Alfresco.util.encodeHTML;

  Alfresco.Aafb = function(htmlId)
  {
    this.name = "Alfresco.Aafb";
    this.id = htmlId;
    this.configDialog = null;

    /**
     * Register this component
     */
    Alfresco.util.ComponentManager.register(this);

    /**
     * Load YUI Components
     */
    Alfresco.util.YUILoaderHelper.require([],this.onComponentsLoaded,this);

    return this;
  };

  YAHOO.extend(Alfresco.Aafb, Alfresco.component.Base,
  {
    /**
     * Object container for initialization options
     *
     * @property options
     * @type object
     */
    options:
    {
      /**
       * The component id
       *
       * @property componentId
       * @type string
       * @default ""
       */
      componentId: "",

      /**
       * The configurable title to display
       *
       * @property titleStr
       * @type string
       * @default ""
       */
      titleStr: "",

      /**
       * The configurable headline to display
       *
       * @property headlineStr
       * @type string
       * @default ""
       */
      headlineStr: "",

      /**
       * The configurable story to display
       *
       * @property storyStr
       * @type string
       * @default ""
       */
      storyStr: ""
    },

    /**
     * Fired by YUI when parent element is available for scripting.
     * Component initialisation, including instantiation of YUI widgets
     * and event listener binding.
     *
     * @method onReady
     */
    onReady: function A_onReady()
    {
      // Add click handler to config Aafb link that will be visible if user
      // is site manager.
      var configFeedLink = Dom.get(this.id + "-configAafb-link");
      if (configFeedLink)
      {
        Event.addListener(configFeedLink,"click",this.onConfigAafbClick,this,true);
      }
    },

    /**
     * Called when the user clicks the config Aafb link.
     * Will open an Aafb config dialog
     *
     * @method onConfigAafbClick
     * @param e The click event
     */
    onConfigAafbClick: function A_onConfigAafbClick(e)
    {
      var actionUrl = Alfresco.constants.URL_SERVICECONTEXT +
       "modules/aafb/config/" + encodeURIComponent(this.options.componentId);

      if (!this.configDialog)
      {
        this.configDialog = new Alfresco.module.SimpleDialog(this.id + "-configDialog").setOptions({
          width: "30em",
          templateUrl: Alfresco.constants.URL_SERVICECONTEXT + "modules/aafb/config",
          actionUrl: actionUrl,
          onSuccess:
          {
            fn: function Aafb_onConfigFeed_callback(response)
            {
              var aafb = response.json;

              // Save values for new config dialog openings
              this.options.titleStr    = (aafb &amp;&amp; aafb.title) ? aafb.title : this.options.titleStr;
              this.options.headlineStr = (aafb &amp;&amp; aafb.headline) ? aafb.headline : this.options.headlineStr;
              this.options.storyStr    = (aafb &amp;&amp; aafb.story) ? aafb.story : this.options.storyStr;

              // Update dashlet body with new values
              Dom.get(this.id + "-title").innerHTML    = aafb ? aafb.title : "";
              Dom.get(this.id + "-headline").innerHTML = aafb ? aafb.headline : "";
              Dom.get(this.id + "-story").innerHTML    = aafb ? aafb.story : "";
            },
            scope: this
          },
          doSetupFormsValidation:
          {
            fn: function Aafb_doSetupForm_callback(form)
            {
              form.addValidation(this.configDialog.id + "-title",
               Alfresco.forms.validation.mandatory, null, "keyup");
              form.addValidation(this.configDialog.id + "-headline",
               Alfresco.forms.validation.mandatory, null, "keyup");
              form.setShowSubmitStateDynamically(true, false);

              Dom.get(this.configDialog.id + "-title").value = this.options.titleStr;
              Dom.get(this.configDialog.id + "-headline").value = this.options.headlineStr;
              Dom.get(this.configDialog.id + "-story").value = this.options.storyStr;
            },
            scope: this
          }
        });
      }
      else
      {
        this.configDialog.setOptions(
        {
          actionUrl: actionUrl
        });
      }
      this.configDialog.show();
    }
  });
})();</code>
    </pre>
<h4>Layout Configuration Dialog</h4>
<p>Next, let&#8217;s look at the implementation of the dialog used to set configuration values. Much like the dashlet itself, the configuration dialog is rendered with a FreeMarker template. In our example, the <code>config-aafb.get.html.ftl</code> file is used as follows:</p>
<pre>
        <code>&lt;div id="${args.htmlid}-configDialog" class="config-aafb"&gt;
   &lt;div class="hd"&gt;${msg("label.dialogTitle")}&lt;/div&gt;

   &lt;div class="bd"&gt;
      &lt;form id="${args.htmlid}-form" action="" method="POST"&gt;
         &lt;div class="yui-gd"&gt;
            &lt;div class="yui-u first"&gt;&lt;label for="${args.htmlid}-title"&gt;${msg("label.title")}:&lt;/label&gt;&lt;/div&gt;
            &lt;div class="yui-u"&gt;&lt;input  id="${args.htmlid}-title" type="text" name="title" value="" maxlength="30" /&gt;&amp;nbsp;*&lt;/div&gt;
         &lt;/div&gt;
         &lt;div class="yui-gd"&gt;
            &lt;div class="yui-u first"&gt;&lt;label for="${args.htmlid}-headline"&gt;${msg("label.headline")}:&lt;/label&gt;&lt;/div&gt;
            &lt;div class="yui-u"&gt;&lt;input  id="${args.htmlid}-headline" type="text" name="headline" value="" maxlength="75" /&gt;&amp;nbsp;*&lt;/div&gt;
         &lt;/div&gt;
         &lt;div class="yui-gd"&gt;
            &lt;div class="yui-u first"&gt;&lt;label for="${args.htmlid}-story"&gt;${msg("label.story")}:&lt;/label&gt;&lt;/div&gt;
            &lt;div class="yui-u"&gt;&lt;input  id="${args.htmlid}-story" type="text" name="story" value="" maxlength="256" /&gt;&lt;/div&gt;
         &lt;/div&gt;
         &lt;div class="bdft"&gt;
            &lt;input type="submit" id="${args.htmlid}-ok" value="${msg("button.ok")}" /&gt;
            &lt;input type="button" id="${args.htmlid}-cancel" value="${msg("button.cancel")}" /&gt;
         &lt;/div&gt;
      &lt;/form&gt;
   &lt;/div&gt;

&lt;/div&gt;</code>
    </pre>
<p>Just like our <code>aafb.get.html.ftl</code>, the <code>config-aafb.get.html.ftl</code> uses properties from its own property file, <code>config-aafb.get.properties</code>.</p>
<h4>Define Configuration Dialog Validation Behavior</h4>
<p>With our dialog in place, let&#8217;s discuss how to define the validation behavior for fields on that dialog.</p>
<p>In the <code>doSetupFormsValidation</code> method we set up validation rules that make both the title and headline fields mandatory, and prevent users from submitting the dialog if the rules aren&#8217;t satisfied. In this method, we also set the form values to the current values of the configuration parameters so users can see what they&#8217;re about to change. This is all done in <code>aafb.js</code> as follows:</p>
<pre>
        <code>doSetupFormsValidation:
{
  fn: function Aafb_doSetupForm_callback(form)
  {
    form.addValidation(this.configDialog.id + "-title", Alfresco.forms.validation.mandatory, null, "keyup");
    form.addValidation(this.configDialog.id + "-headline", Alfresco.forms.validation.mandatory, null, "keyup");
    form.setShowSubmitStateDynamically(true, false);

    Dom.get(this.configDialog.id + "-title").value = this.options.titleStr;
    Dom.get(this.configDialog.id + "-headline").value = this.options.headlineStr;
    Dom.get(this.configDialog.id + "-story").value = this.options.storyStr;
  },
  scope: this
}</code>
    </pre>
<p>Alfresco supplies many other form validation rules as part of its forms service. You can find more <a target="_blank" href="http://wiki.alfresco.com/wiki/Forms">documentation on the Alfresco forms service</a> on the Alfresco Wiki.</p>
<h4>Submit Configuration Dialog</h4>
<p>The configuration dialog is submitted via a <code>POST</code> to a JavaScript controller. The controller is implemented in the <code>config-aafb.post.json.js</code> file. This controller takes the values from the dialog&#8217;s form, sticks them in properties that are persisted, and then sets them on the model so the new values can be delivered back to our waiting callback function. You can see how simple this whole process is here:</p>
<pre>
        <code>var c = sitedata.getComponent(url.templateArgs.componentId);

var title = String(json.get("title"));
var headline = String(json.get("headline"));
var story = String(json.get("story"));

c.properties["title"] = title;
c.properties["headline"] = headline;
c.properties["story"] = story;

model.title = title;
model.headline = headline;
model.story = story;

c.save();</code>
    </pre>
<h4>Define Configuration Dialog Response</h4>
<p>The response from our <code>POST</code> to the JavaScript controller carries our news values back to the <code>aafb.js</code> file in a JSON object. This object is handled by the <code>onSuccess</code> function that we&#8217;ll look at in the next section. The JSON response is defined by a FreeMarker template in the <code>config-aafb.post.json.ftl</code> as follows:</p>
<pre>
        <code>&lt;#escape x as jsonUtils.encodeJSONString(x)&gt;
{
   "title": "${title!''}",
   "headline": "${headline!''}",
   "story": "${story!''}"
}
&lt;/#escape&gt;</code>
    </pre>
<h4>Process Configuration Dialog Response</h4>
<p>The final thing we need to do is define what our dashlet should do when new values are successfully submitted and processed through the configuration dialog. In the <code>onSuccess</code> function we setup a callback mechanism that accepts the JSON response and sets some values. First, we set the values of our custom object. Then we update the contents of the dashlet&#8217;s markup so that users will automatically see the new values. This is all done in <code>aafb.js</code> as follows:</p>
<pre>
        <code>onSuccess:
{
  fn: function Aafb_onConfigFeed_callback(response)
  {
    var aafb = response.json;

    // Save values for new config dialog openings
    this.options.titleStr    = (aafb &amp;&amp; aafb.title) ? aafb.title : this.options.titleStr;
    this.options.headlineStr = (aafb &amp;&amp; aafb.headline) ? aafb.headline : this.options.headlineStr;
    this.options.storyStr    = (aafb &amp;&amp; aafb.story) ? aafb.story : this.options.storyStr;

    // Update dashlet body with new values
    Dom.get(this.id + "-title").innerHTML    = aafb ? aafb.title : "";
    Dom.get(this.id + "-headline").innerHTML = aafb ? aafb.headline : "";
    Dom.get(this.id + "-story").innerHTML    = aafb ? aafb.story : "";
  },
  scope: this
},</code>
    </pre>
<h3>
        <a name="head6" class="section">A Few Words of Advice</a><br />
    </h3>
<p>Now that you&#8217;ve seen how a simple dashlet that supports configuration is assembled, let&#8217;s take a moment to talk about a few of the areas that could trip you up.</p>
<h4>Don&#8217;t Lose Your Head</h4>
<p>Don&#8217;t forget to include the <code>*.get.head.ftl</code> (<code>aafb.get.head.ftl</code> in our example) file in your dashlet. There isn&#8217;t much going on in this file, but without it, you won&#8217;t have access to your <code>*.js</code> file(s) or any custom styles you might define in a <code>*.css</code> file. If you see something like this in your JavaScript console:</p>
<pre>
        <code>Alfresco.Aafb is not a constructor</code>
    </pre>
<p>It&#8217;s likely that the problem is that you&#8217;ve left out your <code>*.get.head.ftl</code> file. This would be a great place to start your troubleshooting efforts. Trust me. I speak from experience.</p>
<h4>Minified JavaScript</h4>
<p>By default, Alfresco is configured to look for minified JavaScript files. JavaScript minification is the process of removing all unnecessary characters from the source to minimize the file size, without changing the JavaScript&#8217;s functionality. This helps improve your site&#8217;s performance, but it can make development a little trickier.</p>
<p>In your <code>*.get.head.ftl</code> file you&#8217;ll see a line like this:</p>
<pre>
        <code>&lt;@script type="text/javascript" src="${page.url.context}/components/dashlets/aafb.js"&gt;&lt;/@script&gt;</code>
    </pre>
<p>This line makes your <code>*.js</code> file available to the rest of the files in your dashlet. But by default, Alfresco will actually replace the reference to <code>aafb.js</code> with a reference to <code>aafb-min.js</code>. So, if you haven&#8217;t created a <code>-min</code> version of your JavaScript, your dashlet won&#8217;t work.</p>
<p>One way to address this is by ensuring that the minified version of your JavaScript file(s) is current and available inside the same folder as your base JavaScript file. You could do this by manually copying and renaming your base JavaScript file after each change (ouch!), or through the use of a development tool such as <a target="_blank" href="http://crockford.com/javascript/jsmin.html">JSMIN</a> to generate JavaScript files that are actually minified.</p>
<p>Alternatively, you could configure Alfresco to not look for the minified JavaScript file during your development process. One simple way to do this is to change the <code>&lt;@script&gt;</code> tag in your <code>*.get.head.ftl</code> file to a <code>&lt;script&gt;</code> tag. This would change the reference in your <code>*.get.head.ftl</code> to look something like:</p>
<pre>
        <code>&lt;script type="text/javascript" src="${page.url.context}/components/dashlets/aafb.js"&gt;&lt;/script&gt;</code>
    </pre>
<h3>
        <a name="head7" class="section">Parting Thoughts</a><br />
    </h3>
<p>There you have it, a straightforward (as straightforward as I can put it anyway) example of a custom dashlet that supports configuration. The number of files required to support configuration can seem intimidating at first, but I hope this article has shown you that once you understand how the files work together, it&#8217;s really not all that complex.</p>
<p>So, now that you know how enable configuration in your own custom dashlets, what will you build? To help you get started, I&#8217;ve included a collection of documentation, links, and source files in the Resources section. Please share your questions, thoughts and ideas in the comments below.  Thanks, and happy configuring!</p>
<h3>
        <a name="head8" class="section">Resources</a><br />
    </h3>
<p>The following links and documents were referenced in writing this article, and are a great source for more information on all of the topics above:</p>
<ul>
<li>
            <a target="_blank" href="http://wiki.alfresco.com/wiki/Web_Scripts">Alfresco Web Scripts</a>
        </li>
<li>
            <a target="_blank" href="http://wiki.alfresco.com/wiki/3.0_Web_Scripts_Framework">Web Scripts Framework</a>
        </li>
<li>
            <a target="_blank" href="http://wiki.alfresco.com/wiki/Surf_Platform_-_Developers_Guide">Alfresco Surf Platform &#8211; Developers Guide</a>
        </li>
<li>
            <a target="_blank" href="http://drquyong.com/myblog/?p=25">Dr. Q&#8217;s Workshop &#8211; Hello World Dashlet</a>
        </li>
<li>
            <a target="_blank" href="http://www.bluefishgroup.com/library/2010/painless-alfresco-development-source-code-organization/">Blue Fish &#8211; Alfresco Source Code Organization</a>
        </li>
<li>
            <a target="_blank" href="http://wiki.alfresco.com/wiki/Main_Page">Alfresco Wiki</a>
        </li>
<li>
            <a target="_blank" href="http://crockford.com/javascript/jsmin.html">JSMin &#8211; The JavaScript Minifier</a>
        </li>
<li>
            <a href="/article-assets/code/ExampleConfigurableDashletSource.zip">Example Dashlet Source Code</a>
        </li>
</ul>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2010/making-alfresco-share-dashlets-configurable/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Texans: Have Lunch and Learn About Alfresco 3.3</title>
		<link>http://www.bluefishgroup.com/2010/texans-have-lunch-and-learn-about-alfresco-33/</link>
		<comments>http://www.bluefishgroup.com/2010/texans-have-lunch-and-learn-about-alfresco-33/#comments</comments>
		<pubDate>Mon, 05 Apr 2010 21:10:01 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=420</guid>
		<description><![CDATA[Blue Fish and Alfresco are hosting a Lunch and Learn to show folks some of the cool new features coming out in Alfresco 3.3 later this month. If you live in Texas, we&#8217;d love to see you. The event will preview Alfresco 3.3, the latest release from the leading open source ECM provider. We&#8217;re hosting [...]]]></description>
				<content:encoded><![CDATA[<p>Blue Fish and Alfresco are hosting a Lunch and Learn to show folks some of the cool new features coming out in Alfresco 3.3 later this month. If you live in Texas, we&#8217;d love to see you.</p>
<p>The event will preview Alfresco 3.3, the latest release from the leading open source ECM provider. We&#8217;re hosting this two-hour session in five Texas cities, so hopefully you can find one to attend. All sessions run from 11:00 – 1:00 and lunch will be provided. </p>
<ul>
<li><strong>Dallas</strong> – Tuesday, April 20</li>
<li><strong>Ft. Worth</strong> – Wednesday, April 21</li>
<li><strong>Austin</strong> – Thursday, April 22</li>
<li><strong>San Antonio</strong> – Friday, April 23</li>
<li><strong>Houston</strong> – Tuesday, April 27</li>
</ul>
<p><a href="http://www.alfresco.com/about/events/2010/04/alfresco-lunch-and-learns-april-2010/"><strong>Register for all Lunch and Learns</strong></a> on the Alfresco web site.</p>
<p>This session going to be great for CIOs, IT Managers, or anyone else considering Alfresco for an ECM initiative.  During the event, we&#8217;ll cover the following topics:</p>
<ul>
<li><b>Sneak Preview of Alfresco 3.3</b> – Includes CMIS 1.0, enhancements to Alfresco Share, and IBM Lotus integration</li>
<li><b>Major WCM Enhancements</b> – Demonstration of some exciting new features for editing web content and deploying web sites</li>
</ul>
<p>Space is limited, so please <a href="http://www.alfresco.com/about/events/2010/04/alfresco-lunch-and-learns-april-2010/">register early</a> to secure your place.</p>
<p>I hope to see you there.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2010/texans-have-lunch-and-learn-about-alfresco-33/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Alfresco is a Disruptive Force in the ECM Industry</title>
		<link>http://www.bluefishgroup.com/2010/alfresco-is-a-disruptive-force-in-the-ecm-industry/</link>
		<comments>http://www.bluefishgroup.com/2010/alfresco-is-a-disruptive-force-in-the-ecm-industry/#comments</comments>
		<pubDate>Mon, 29 Mar 2010 14:21:55 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=418</guid>
		<description><![CDATA[At Blue Fish, most of our business is related to either Documentum or Alfresco. Our clients that use Documentum are all companies you recognize – Wells Fargo, Southwest Airlines, Bausch + Lomb. Many of our clients that use Alfresco are great companies that you may not have heard of before &#8211; American Bureau of Shipping, [...]]]></description>
				<content:encoded><![CDATA[<p>At Blue Fish, most of our business is related to either Documentum or Alfresco. Our clients that use Documentum are all companies you recognize – Wells Fargo, Southwest Airlines, Bausch + Lomb. Many of our clients that use Alfresco are great companies that you may not have heard of before &#8211; American Bureau of Shipping, Nanston Dental Group, Drilling Info. </p>
<p>Why is that? </p>
<p>The answer is that Alfresco is bringing the benefits of Enterprise Content Management to companies that don&#8217;t have millions of dollars to spend on ECM solutions. It&#8217;s also bringing ECM to smaller business problems that can&#8217;t justify big money to solve them.</p>
<p>Alfresco is a disruptive force in the ECM industry, similar to the way that SalesForce.com disrupted traditional CRM vendors like Seibel. Let&#8217;s look at how the two compare.</p>
<p>At Blue Fish, we use SalesForce, and we would never in a million years use Seibel. For a sales team of only 2 people, it&#8217;s just not worth it. But SalesForce gives us a world-class CRM solution for a price that we can afford. SalesForce isn&#8217;t just for small shops, either. Dell uses SalesForce, and they have one of the largest sales teams in the world. That&#8217;s true disruption, and it all but put Seibel out of business.</p>
<p>SalesForce did this by using a SaaS business model to dramatically lower the Total Cost of Ownership (TCO) of CRM solutions. </p>
<ul>
<li>SalesForce is <strong>cheaper for me to acquire</strong> (its per user pricing is less than the competition)</li>
<li>SalesForce is <strong>cheaper for me to operate</strong> (I have no servers to maintain and no dependencies on databases, etc.)</li>
<li>SalesForce is <strong>cheaper for me to support</strong> and maintain (no backups, no servers crashing, and I don&#8217;t have to do any upgrades myself)</li>
</ul>
<p>Now, SalesForce&#8217;s customers don&#8217;t care about the cloud, SaaS, or any of that business model stuff – they just want it to be cheap. It is, and that changed the world of CRM.</p>
<p>Alfresco is doing something similar in the world of ECM. They are going about it differently, but they are shooting for the same result.  Alfresco uses an open source model that lets their customers try before they buy and do so without ever talking to a sales rep. Eventually, companies who rely on Alfresco for their critical business data will want to buy an Enterprise subscription with a support agreement, and that&#8217;s how Alfresco makes their money. </p>
<p>But that&#8217;s not really disruptive (it&#8217;s a clever marketing strategy, but it&#8217;s not truly disruptive). What&#8217;s disruptive is the price of their Enterprise license – it&#8217;s dirt cheap. You can get a fully supported version of Alfresco that can support hundreds of users for less than $20,000 a year. Compare that to the traditional players like EMC and IBM who would charge hundreds of thousands of dollars for a similar solution, and you start to see what I&#8217;m talking about.</p>
<p>Alfresco is also cheaper and easier to operate and maintain than traditional ECM solutions. Because of its open source heritage, it can operate on an open source stack, with open source operating systems, databases, and application servers. That reduces the cost of the infrastructure required to run it.</p>
<p>And Alfresco is easier to implement and extend. Because it has come to market recently, it uses modern application development and deployment technologies. Alfresco runs in a Java application server, so you don&#8217;t have to learn new deployment or monitoring procedures. Developers extend it using web services and lightweight web scripts, which are easier to learn. And most importantly, you have access to the source code (even for the Enterprise Edition), so it&#8217;s a thousand times easier to find a defect and fix it or to follow Alfresco&#8217;s patterns when developing your own extensions.</p>
<p>There are places where the big traditional ECM players still make sense. If you want to run your ECM solution on a mainframe, IBM is the only game in town. If you are a pharmaceutical company with regulated content, Documentum is the strongest bet. If you&#8217;ve standardized on Microsoft throughout the company, SharePoint might be for you. </p>
<p>But if you are looking for the best value – a full-featured ECM solution that won&#8217;t break the bank, Alfresco is the best bet.</p>
<p>As a result, companies that never considered ECM solutions are looking at them for the first time.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2010/alfresco-is-a-disruptive-force-in-the-ecm-industry/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New Alfresco Release 3.2r Now Available</title>
		<link>http://www.bluefishgroup.com/2010/new-alfresco-release-32r-now-available/</link>
		<comments>http://www.bluefishgroup.com/2010/new-alfresco-release-32r-now-available/#comments</comments>
		<pubDate>Tue, 23 Feb 2010 18:57:47 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=417</guid>
		<description><![CDATA[Alfresco has just released a new version with some improvements on the WCM side of the house. The version is 3.2r, a dot-release (sort of) that adds additional features to the 3.2 release. Repository Access from Alfresco Share – The most frequently requested product enhancement is now available. The Document Library in Alfresco Share now [...]]]></description>
				<content:encoded><![CDATA[<p>Alfresco has just released a new version with some improvements on the WCM side of the house. The version is 3.2r, a dot-release (sort of) that adds additional features to the 3.2 release.</p>
<ul>
<li><strong>Repository Access from Alfresco Share</strong> – The most frequently requested product enhancement is now available. The Document Library in Alfresco Share now allows users to quickly move from working within a project site to full access to the general document management repository.</li>
<li><strong>Web Content Deployment Options</strong> – This release sees Alfresco include the ability to deploy web content to an Alfresco DM repository. This can be used to serve personalized content and can be clustered to achieve maximum performance and scalability for Alfresco-powered websites.</li>
<li><strong>Enhanced Document Browsing Options</strong> – This allows users to browse the document repository using folders, Cloud Tags, Category lists or by Favorites. These new options make it even easier to find the correct content.</li>
<li><strong>Faster, More Stable Document Conversions</strong> – The new OpenOffice transformation subsystem sports the ability to create pools of fully managed OpenOffice services to dramatically improve document conversion speed, reliability and overall system stability.</li>
<li><strong>New Portal and Portlet Development Options</strong> – With this release, Alfresco includes support for portals and portlets, meaning developers can now create new Alfresco-powered portlets and deploy them into a portal with support for single sign-on (SSO) built-in.</li>
<li><strong>Records Management-ready</strong> – Alfresco Enterprise Edition 3.2r is ready to accept the fully certified, DoD 5015.02-certified Records Management module. </li>
</ul>
<p>I&#8217;m most excited about the improvements to Share. We&#8217;ve been using Share a lot lately, and it&#8217;s becoming my preferred UI for WCM projects as well as DM projects. It&#8217;s evolving quickly, and I love it when they release a new version.</p>
<p>You can download a trial version here: <a href="http://www2.alfresco.com/e/1234/ry/GIEWE/177864364">http://www2.alfresco.com/e/1234/ry/GIEWE/177864364</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2010/new-alfresco-release-32r-now-available/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Webinar: Making Web Content Easy with Alfresco Share 3.2</title>
		<link>http://www.bluefishgroup.com/2010/webinar-making-web-content-easy-with-alfresco-share-32/</link>
		<comments>http://www.bluefishgroup.com/2010/webinar-making-web-content-easy-with-alfresco-share-32/#comments</comments>
		<pubDate>Fri, 19 Feb 2010 11:15:16 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Webinars]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=416</guid>
		<description><![CDATA[Yesterday, I presented a webinar with Josh Toub describing how we have customized Alfresco Share to streamline the content creation process for web sites. Josh leads our Alfresco team here at Blue Fish, and he&#8217;s created a really great solution that fills in some gaps in Alfresco&#8217;s WCM offering. Some of the features included in [...]]]></description>
				<content:encoded><![CDATA[<p>Yesterday, I presented a webinar with Josh Toub describing how we have customized Alfresco Share to streamline the content creation process for web sites. Josh leads our Alfresco team here at Blue Fish, and he&#8217;s created a really great solution that fills in some gaps in Alfresco&#8217;s WCM offering. Some of the features included in the demo are:</p>
<ul>
<li><strong>In-Context Editing</strong> &#8211; Create and edit content right from your web site (no need to log into a WCM system)</li>
<li><strong>Sexy New Web Page Forms/Templates</strong> &#8211; We&#8217;re using the fancy new forms service in Share, which makes our templates really pretty and easy to use</li>
<li><strong>An Easy Way to Preview Changes Before They Go Live</strong> &#8211; You can put your web site into &#8220;preview mode&#8221; to see what the site will look like when the new pages are approved</li>
<li><strong>An Easy Way to Approve Changes</strong> &#8211; Reviewing and approving changes is a breeze</li>
</ul>
<p>You can see a recorded version of the webinar here: <a href="http://blogs.alfresco.com/wp/webcasts/2010/02/making-web-content-management-easy-with-alfresco-share-32/">Making Web Content Easy with Alfresco Share 3.2</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2010/webinar-making-web-content-easy-with-alfresco-share-32/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>EMC Replaces Web Publisher With FatWire</title>
		<link>http://www.bluefishgroup.com/2010/emc-replaces-web-publisher-with-fatwire/</link>
		<comments>http://www.bluefishgroup.com/2010/emc-replaces-web-publisher-with-fatwire/#comments</comments>
		<pubDate>Thu, 18 Feb 2010 22:11:42 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=415</guid>
		<description><![CDATA[Big news out of EMC this week. They have purchased a large stake in FatWire, a competing Web Content Management company. Even bigger news is that Documentum Web Publisher, EMC&#8217;s web content management solution, is being replaced by FatWire&#8217;s &#8220;Web Experience Management&#8221; (WEM) solution. The deal looks like this: FatWire will resell EMC&#8217;s digital asset [...]]]></description>
				<content:encoded><![CDATA[<p>Big news out of EMC this week. They have purchased a large stake in FatWire, a competing Web Content Management company. Even bigger news is that Documentum Web Publisher, EMC&#8217;s web content management solution, is being replaced by FatWire&#8217;s &#8220;Web Experience Management&#8221; (WEM) solution.</p>
<p>The deal looks like this: FatWire will resell EMC&#8217;s digital asset management software, and EMC will resell FatWire&#8217;s WCM software. </p>
<h3>What&#8217;s So Great About FatWire?</h3>
<p>FatWire is the largest independent WCM (or as they like to be called, WEM) software vendor. They have over 500 enterprise accounts and 200 employees. Most analysts consider FatWire to be one of the best solutions for WCM/WEM. So they have a lot of credibility behind them.</p>
<p>The FatWire solution is much more holistic than Web Publisher. While Web Publisher is focused only on the creation, approval, and management of web content, FatWire also focuses on delivery and presentation of that content to end users (web site visitors). With FatWire, you get a much more sophisticated solution &#8220;out of the box&#8221;, while getting the same types of features with a Web Publisher-driven solution would require thousands of hours of development effort from your web team.</p>
<p>Here are some of the features FatWire has that will be new to Web Publisher owners:</p>
<ul>
<li><b>Drag and Drop Authoring</b> &#8211; FatWire&#8217;s user interface allows web page authors to drag rich page components from a &#8220;library&#8221; into a web page. For example, you can drag a &#8220;slideshow&#8221; component into a web page and configure it to cycle through a set of images. FatWire has a bunch of built-in components for things like this, so you don&#8217;t have to be a web design expert to create a rich user experience.</li>
<li><b>Personalization and Segment Targeting</b> &#8211; FatWire has robust targeting and personalization features that can target certain content to certain segments of your visitors. These segments can be defined based on &#8220;known&#8221; profile information (like a customer&#8217;s address from your CRM system) or they can be created based on the visitor&#8217;s behavior on the site. So not only can you offer, say, coats and snowshoes to someone that lives in Alaska, you can keep track of the color of other items they&#8217;ve looked at on your site and then show them coats and snowshoes in those colors.</li>
<li><b>User Generated Content</b> &#8211; FatWire has built-in support for user generated content such as ratings, reviews, and comments. And it comes complete with a set of moderation features that allow your content managers to approve the user generated content before it goes live on your site.</li>
<li><b>Analytics</b> &#8211; FatWire includes rich analytics that help you understand what content is most popular and is driving the highest conversion rates, etc. It can do this not only at the page level, but also at the component level, so if you have a rotating set of product images on your home page, you can see which image is doing the best job of catching your visitor&#8217;s attention.</li>
<li><b>Edge caching</b> &#8211; FatWire includes built-in edge caching servers called &#8220;satellite servers&#8221; that allow all these fancy targeting rules to work in a high-performance manner.
</ul>
<h3>Integrating with Documentum</h3>
<p>FatWire has its own architecture, repository, and technology stack that differ from Documentum&#8217;s, so it breaks Documentum&#8217;s vision of a single integrated repository for all enterprise content. And since EMC didn&#8217;t fully acquire FatWire, there are no plans to replace the FatWire repository with the Documentum repository.</p>
<p>However, FatWire does have an integration with Documentum that will synchronize content from Documentum into FatWire. When you make a change to the content in Documentum, it will automatically update in FatWire (and on your web site), or optionally launch a FatWire workflow to be approved before it goes live. The main use case I see for this is the ability to embed into your FatWire web pages the digital assets (videos, etc.) that are stored in Documentum&#8217;s Digital Asset Management solution. </p>
<p>Later this year, there will be an integration that goes the other way, allowing FatWire content to be replicated into Documentum as well.</p>
<h3>What is going to happen to Web Publisher?</h3>
<p>Peggy Ringhausen, an old friend of mine and the WCM product manager at EMC, says that the new FatWire solution is the wave of the future and that they will be retiring Web Publisher, Page Builder, and the other products in the WCM product line. No date has been announced for this, but it probably won&#8217;t happen for at least three years.</p>
<p>EMC says they have some licensing deals that allow existing Web Publisher owners to get their hands on the new FatWire solution, but you shouldn&#8217;t expect it to be a free upgrade.
<p>It will be interesting to see how existing Web Publisher owners react to this news. On the one hand, their existing investment is in jeopardy, but on the other hand, the replacement seems like a much stronger solution.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2010/emc-replaces-web-publisher-with-fatwire/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>New Alfresco Article on Improving the Way Custom Code is Organized</title>
		<link>http://www.bluefishgroup.com/2010/new-alfresco-article-on-improving-the-way-custom-code-is-organized/</link>
		<comments>http://www.bluefishgroup.com/2010/new-alfresco-article-on-improving-the-way-custom-code-is-organized/#comments</comments>
		<pubDate>Wed, 03 Feb 2010 19:45:46 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=414</guid>
		<description><![CDATA[Josh Toub leads the Alfresco team here at Blue Fish, and he&#8217;s just written a new article that can help Alfresco developers improve the maintainability and supportability of their Alfresco solutions. When a developer customizes Alfresco to add a new webscript or portlet or modify an existing class, the common practice is to create new [...]]]></description>
				<content:encoded><![CDATA[<p>Josh Toub leads the Alfresco team here at Blue Fish, and he&#8217;s just written a new article that can help Alfresco developers <a href="http://www.bluefishgroup.com/library/2010/painless-alfresco-development-source-code-organization/">improve the maintainability and supportability of their Alfresco solutions</a>.</p>
<p>When a developer customizes Alfresco to add a new webscript or portlet or modify an existing class, the common practice is to create new source code files in the same directory structure as the out-of-the-box Alfresco source files. This can cause maintenance problems because it&#8217;s hard to tell which files have been modified and which ones were original. It makes troubleshooting and upgrading much more difficult, and it&#8217;s harder to share your code or reuse it in other solutions.</p>
<p>Josh&#8217;s article shows how you can configure Alfresco to look in a special place for your custom code so that you can keep it out of the main Alfresco directory structure. Read <a href="http://www.bluefishgroup.com/library/2010/painless-alfresco-development-source-code-organization/">Painless Alfresco Development: Improving Supportability through Source Code Organization</a> for more information.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2010/new-alfresco-article-on-improving-the-way-custom-code-is-organized/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Painless Alfresco Development: Improving Supportability through		Source Code Organization</title>
		<link>http://www.bluefishgroup.com/2010/painless-alfresco-development-source-code-organization/</link>
		<comments>http://www.bluefishgroup.com/2010/painless-alfresco-development-source-code-organization/#comments</comments>
		<pubDate>Wed, 03 Feb 2010 12:00:00 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Custom ECM Solutions]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=413</guid>
		<description><![CDATA[Introduction Note: This article assumes that you already know the ins and outs of basic Spring configuration and that you know how to build basic Alfresco extensions. If you need an introduction to these concepts, I recommend you start with the Alfresco development wiki . Alfresco is great. It&#8217;s a rock solid content management and [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Introduction</a><br />
    </h3>
<p class="note">
        <b>Note: </b><br />
			This article assumes that you already know the ins and outs of basic<br />
			Spring configuration and that you know how to build basic Alfresco<br />
			extensions. If you need an introduction to these concepts, I<br />
			recommend you start with the<br />
			<a target="_blank" href="http://wiki.alfresco.com/wiki/Developer_Guide">Alfresco development wiki</a><br />
			.
		</p>
<p>
			Alfresco is great. It&rsquo;s a rock solid content management and<br />
			collaboration platform with an exciting roadmap. Although it&rsquo;s only a<br />
			handful of years old, it can go toe to toe with the legacy players in<br />
			the field and often come out ahead. It has an immensely flexible<br />
			architecture that makes it pretty much as easy as possible to extend<br />
			and adapt the base Alfresco offerings to meet specific requirements.<br />
			I love having access to the source. I love that you can &#8220;try before<br />
			you buy.&#8221; I love Alfresco&rsquo;s enormous community that does everything<br />
			from supporting end users to evolving core products. I love that<br />
			Alfresco is a disruptive player poised to drastically alter the<br />
			landscape of the otherwise stodgy world of Enterprise Content<br />
			Management.
        </p>
<p>
			Ok, so what don&rsquo;t I love about Alfresco? Well, the commonly<br />
			practiced methods for extending Alfresco sometimes force me to<br />
			violate certain development best practices, like encapsulating and<br />
			isolating custom source code. For many types of extensions,<br />
			out-of-the-box Alfresco requires you to distribute source code across<br />
			many different directories, and those directories are typically<br />
			nested inside of stock Alfresco directories. For example, a simple<br />
			custom dashlet might include the following files:
        </p>
<div align="center">
        <img src="/article-assets/images/alf-code-org/TypicalSource.jpg" border="0" alt="Fig. 1: Typical source code organization for an Alfresco Share extension.">
<p class="figure">
            <b><br />
              Figure 1:<br />
            </b> Conventional source code organization for an Alfresco Share extension.</p>
</p></div>
<p>
			And these files would get deployed alongside stock Alfresco source<br />
			files within the web application like so:
		</p>
<div align="center">
        <img src="/article-assets/images/alf-code-org/TypicalDeployed.jpg" border="0" alt="Fig. 2: Conventionally organized Alfresco Share extension files are deployed alongside out-of-the-box files, making it difficult to easily identify what is custom and what is stock.">
<p class="figure">
            <b><br />
              Figure 2:<br />
            </b> Conventionally organized Alfresco Share extension files are deployed alongside out-of-the-box files, making it difficult to easily identify what is custom and what is stock.</p>
</p></div>
<p>
			As you can see, the extension source files live underneath the<br />
			<code>alfresco</code> directory right alongside stock Alfresco files and<br />
			potentially files from every other extension that might be deployed.<br />
			This makes it difficult to quickly identify which files make up the<br />
			extension. From a development best practices perspective, it is<br />
			simply bad hygiene to pollute Alfresco&rsquo;s directories with dozens of<br />
			custom files and directories.
        </p>
<p>
			Thankfully, Alfresco&rsquo;s flexible Spring-based configuration<br />
			architecture makes it easy to structure an Alfresco development<br />
			project in such a way that cleanly separates custom files from<br />
			everything else. Before we get into the details of these Spring<br />
			configuration mechanics, let&rsquo;s take a look at what I&rsquo;d like my source<br />
			tree to look like.
        </p>
<h3>
        <a name="head2" class="section">Preferred Source Code Organization</a><br />
    </h3>
<p>
			There are many ways you can organize your source such that it is<br />
			isolated from the out-of-the-box distribution. To make my source<br />
			trees feel familiar to seasoned Alfresco developers, I like to create<br />
			source structures that closely mirror the out-of-the-box Alfresco and<br />
			Share web applications. Revisiting the source for our initial<br />
			extension example, I would structure it like so:
		</p>
<div align="center">
        <img src="/article-assets/images/alf-code-org/IdealSource.jpg" border="0" alt="Fig. 3: My preferred source code organizational structure for Alfresco extensions.">
<p class="figure">
            <b><br />
              Figure 3:<br />
            </b> My preferred source code organizational structure for Alfresco extensions.</p>
</p></div>
<p>
			I find that isolating my files like this makes it easier to debug,<br />
			package, and distribute my extensions because they readily stand out<br />
			from the stock Alfresco files. It also tends to make it easier for<br />
			other developers to understand how my extensions work because they<br />
			can quickly identify all of the files that comprise each extension.<br />
			Here&rsquo;s what my deployed dashlet source looks like with this<br />
			organizational structure:
		</p>
<div align="center">
        <img src="/article-assets/images/alf-code-org/IdealDeployed.jpg" border="0" alt="Fig. 4: With my preferred source code organizational structure, all of the custom files get deployed under a single folder.">
<p class="figure">
            <b><br />
              Figure 4:<br />
            </b> With my preferred source code organizational structure, all of the custom files get deployed under a single folder.</p>
</p></div>
<p>
			Look at that&mdash;all of my source files are grouped under a common<br />
			folder!
		</p>
<h3>
        <a name="head3" class="section">A Tale of Two Web Apps</a><br />
    </h3>
<p>
			You may have noticed that I begin my source tree with a folder named<br />
			<code>share</code>. This folder maps directly to the Share web application<br />
			deployed by Alfresco. Similarly, if my extensions required that files<br />
			be deployed to the Alfresco web application, I would organize those<br />
			files under a root folder called <code>alfresco</code>.
</p>
<p>
			If you&rsquo;re wondering why an extension might require that files be<br />
			deployed to multiple web applications, just remember how Alfresco is<br />
			architected: the <em>Alfresco</em> web application hosts the core repository,<br />
			all of the webscripts that provide access to the core repository, and<br />
			the Java Server Faces-based Alfresco Explorer web client; and the<br />
			<em>Share</em> web application hosts the <a target="_blank" href="http://www.springsource.org/extensions/se-surf">Spring Surf</a>-based Alfresco Share user<br />
			interface and its supporting webscripts.
</p>
<p>
			If you take a look at your application server&rsquo;s webapp directory after<br />
			installing Alfresco, you should see something like this:
		</p>
<div align="center">
        <img src="/article-assets/images/alf-code-org/TwoWebApps.jpg" border="0" alt="Fig. 5: Alfresco is typically deployed as two (or more) web applications. In this example, &quot;alfresco&quot; hosts the Alfresco repository, and &quot;share&quot; hosts the Share UI.">
<p class="figure">
            <b><br />
              Figure 5:<br />
            </b> Alfresco is typically deployed as two (or more) web applications. In this example, &#8220;alfresco&#8221; hosts the Alfresco repository, and &#8220;share&#8221; hosts the Share UI.</p>
</p></div>
<p>The Share web application interacts with the Alfresco repository by<br />
			calling the webscripts published by the Alfresco web application. It<br />
			is important to remember this because your Alfresco customizations<br />
			may reside in one web app, the other, or both.
</p>
<h4>Resolving Custom Resources</h4>
<p>
			In order for Alfresco to be able to find the files in my preferred<br />
			folder structure, we need to tell Alfresco where to look. Resources<br />
			in Alfresco&mdash;be they XML configuration files, Freemarker templates,<br />
			webscript implementations, and others&mdash;are resolved using Spring&rsquo;s<br />
			configuration framework. Furthermore, Alfresco knows to look for a<br />
			handful of specific custom Spring configuration files to pick up<br />
			custom values that override default values defined in Alfresco&rsquo;s<br />
			default Spring configuration. This means that the particular methods<br />
			for how Alfresco resolves resources can be easily changed simply by<br />
			adding a few<br />
			<code>&lt;bean&gt;</code> entries to one of these custom Spring configuration files. The<br />
				specific files that need to be edited are:
		</p>
<ul>
<li>
            <code>/WEB-INF/classes/alfresco/web-extension/custom-slingshot-application-context.xml</code><br />
				(for the Share webapp)
        	</li>
<li>
            <code>/WEB-INF/classes/alfresco/extension/custom-web-context.xml</code> (for<br />
				the Alfresco webapp)
        	</li>
</ul>
<p>
			You should be aware that these files may not yet exist in your Alfresco<br />
			implementation, particularly if you have not built any extensions<br />
			yet. If necessary, go ahead and create them with the following empty<br />
			Spring bean configuration:
</p>
<p><pre>
            <code>
&lt;?xml version='1.0' encoding='UTF-8'?&gt;
&lt;!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'&gt;
&lt;!-- Top-level imports of XML configuration --&gt;
&lt;beans&gt;

&lt;/beans&gt;
</code>
        </pre>
</p>
<p>
			Now comes the tough part&mdash;finding out which Spring beans need to be<br />
			overridden to pick up your particular resources. Thankfully, Alfresco<br />
			follows a nice naming convention for their Spring beans and has named<br />
			the various search paths with names containing the string<br />
			&#8220;<code>searchpath</code>.&#8221; This makes it easy to find all of the default search<br />
			path configurations&mdash;just use your favorite IDE to search for the<br />
			string <code>id='*searchpath'</code> across all xml files in the Alfresco source<br />
			tree. In the current 3.2 Community source, this yields 14 distinct<br />
			matches for the Share webapp:
	</p>
<ul>
<li>
            <code><br />
				webframework.searchpath</code>
        </li>
<li>
            <code><br />
				webframework.templates.searchpath</code>
        </li>
<li>
            <code><br />
				webframework.searchpath.chrome</code>
        </li>
<li>
            <code><br />
				webframework.searchpath.component</code>
        </li>
<li>
            <code><br />
				webframework.searchpath.componenttype</code>
        </li>
<li>
            <code><br />
				webframework.searchpath.configuration</code>
        </li>
<li>
            <code><br />
				webframework.searchpath.contentassociation</code>
        </li>
<li>
            <code><br />
				webframework.searchpath.page</code>
        </li>
<li>
            <code><br />
				webframework.searchpath.pageassociation</code>
        </li>
<li>
            <code><br />
				webframework.searchpath.pagetype</code>
        </li>
<li>
            <code><br />
				webframework.searchpath.templateinstance</code>
        </li>
<li>
            <code><br />
				webframework.searchpath.templatetype</code>
        </li>
<li>
            <code><br />
				webframework.searchpath.theme</code>
        </li>
<li>
            <code><br />
				webframework.presets.searchpath</code>
        </li>
</ul>
<p>And one match for the Alfresco webapp:
</p>
<ul>
<li>
            <code>webscripts.searchpath</code>
        </li>
</ul>
<p>
			To override one of these search paths, start by copying and pasting the<br />
			appropriate bean definition into your custom configuration<br />
			(<code>custom-slingshot-application-context.xml</code> for the Share webapp or<br />
			<code>custom-web-context.xml</code> for the Alfresco webapp). For example, let&rsquo;s<br />
			assume that you have created a new Share component whose source files<br />
			you would like to keep separate from the out-of-the-box Share source.<br />
			You would copy this from <code>slingshot-application-context.xml</code> into<br />
			<code>custom-slingshot-application-context.xml</code>:</p>
<p><pre>
            <code>
   &lt;bean id="webframework.searchpath.component" class="org.alfresco.web.scripts.SearchPath"&gt;
      &lt;property name="searchPath"&gt;
         &lt;list&gt;
         	&lt;ref bean="webframework.classpathstore.component.custom" /&gt;
            &lt;ref bean="webframework.classpathstore.component" /&gt;
         &lt;/list&gt;
      &lt;/property&gt;
   &lt;/bean&gt;
</code>
        </pre>
</p>
<p>
			Next, create a new bean that knows how to find your resources. Most of the<br />
			time, you will be want to simply extend Alfresco&rsquo;s<br />
			<code>webframework.classpathstore</code> bean so that it looks in specific paths<br />
			within the classpath. Continuing the above example, let&rsquo;s create a<br />
			bean that looks for component definitions in<br />
			<code>bluefishgroup/share-ext/site-data/components</code>:
</p>
<p><pre>
            <code>
	&lt;bean id="bluefishgroup.components" parent="webframework.classpathstore"&gt;
		&lt;property name="mustExist"&gt;
			&lt;value&gt;true&lt;/value&gt;
		&lt;/property&gt;
		&lt;property name="classPath"&gt;
			&lt;value&gt;bluefishgroup/site-data/components&lt;/value&gt;
		&lt;/property&gt;
	&lt;/bean&gt;
</code>
        </pre>
</p>
<p>Finally, update the bean definition you copied to reference your<br />
			new bean:</p>
<p><pre>
            <code>
   &lt;bean id="webframework.searchpath.component" class="org.alfresco.web.scripts.SearchPath"&gt;
      &lt;property name="searchPath"&gt;
         &lt;list&gt;
			&lt;ref bean="bluefishgroup.components" /&gt;
            &lt;ref bean="webframework.classpathstore.component.custom" /&gt;
			&lt;ref bean="webframework.classpathstore.component" /&gt;
         &lt;/list&gt;
      &lt;/property&gt;
   &lt;/bean&gt;
</code>
        </pre>
</p>
<p>Now Share will search for our component definitions in<br />
			<code>bluefishgroup/share-ext/site-data/components</code> in addition to the<br />
			default locations. Wasn&rsquo;t that easy? To make it even more convenient,<br />
			I use a template <code>custom-slingshot-application-context.xml</code> that<br />
			overrides all of the default search path beans so that all I need to<br />
			do when I start a new Alfresco development project is add the<br />
			specific paths. Here is the template configuration for you to use in<br />
			your own projects:
</p>
<p><pre>
            <code>
&lt;?xml version='1.0' encoding='UTF-8'?&gt;
&lt;!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'&gt;

&lt;beans&gt;

	&lt;!-- Chrome search path overrides --&gt;

	&lt;bean id="bluefishgroup.chrome" parent="webframework.classpathstore"&gt;
		&lt;property name="mustExist"&gt;
			&lt;value&gt;false&lt;/value&gt;
		&lt;/property&gt;
		&lt;property name="classPath"&gt;
			&lt;value&gt;bluefishgroup/site-data/pages/chrome&lt;/value&gt;
		&lt;/property&gt;
	&lt;/bean&gt;

	&lt;bean id="webframework.searchpath.chrome" class="org.alfresco.web.scripts.SearchPath"&gt;
		&lt;property name="searchPath"&gt;
			&lt;list&gt;
				&lt;ref bean="bluefishgroup.chrome" /&gt;
				&lt;ref bean="webframework.remotestore.chrome" /&gt;
				&lt;ref bean="webframework.classpathstore.chrome.custom" /&gt;
				&lt;ref bean="webframework.classpathstore.chrome" /&gt;
			&lt;/list&gt;
		&lt;/property&gt;
	&lt;/bean&gt;

	&lt;!-- Component search path overrides --&gt;

	&lt;bean id="bluefishgroup.components" parent="webframework.classpathstore"&gt;
		&lt;property name="mustExist"&gt;
			&lt;value&gt;false&lt;/value&gt;
		&lt;/property&gt;
		&lt;property name="classPath"&gt;
			&lt;value&gt;bluefishgroup/site-data/components&lt;/value&gt;
		&lt;/property&gt;
	&lt;/bean&gt;

	&lt;bean id="webframework.searchpath.component" class="org.alfresco.web.scripts.SearchPath"&gt;
		&lt;property name="searchPath"&gt;
			&lt;list&gt;
				&lt;ref bean="bluefishgroup.components" /&gt;
				&lt;ref bean="webframework.remotestore.component" /&gt;
				&lt;ref bean="webframework.classpathstore.component.custom" /&gt;
				&lt;ref bean="webframework.classpathstore.component" /&gt;
			&lt;/list&gt;
		&lt;/property&gt;
	&lt;/bean&gt;

	&lt;!-- Component types search path overrides --&gt;

	&lt;bean id="bluefishgroup.componentTypes" parent="webframework.classpathstore"&gt;
		&lt;property name="mustExist"&gt;
			&lt;value&gt;false&lt;/value&gt;
		&lt;/property&gt;
		&lt;property name="classPath"&gt;
			&lt;value&gt;bluefishgroup/site-data/component-types&lt;/value&gt;
		&lt;/property&gt;
	&lt;/bean&gt;

	&lt;bean id="webframework.searchpath.componenttype" class="org.alfresco.web.scripts.SearchPath"&gt;
		&lt;property name="searchPath"&gt;
			&lt;list&gt;
				&lt;ref bean="bluefishgroup.componentTypes" /&gt;
				&lt;ref bean="webframework.remotestore.componenttype" /&gt;
				&lt;ref bean="webframework.classpathstore.componenttype.custom" /&gt;
				&lt;ref bean="webframework.classpathstore.componenttype" /&gt;
			&lt;/list&gt;
		&lt;/property&gt;
	&lt;/bean&gt;

	&lt;!-- Configuration search path overrides --&gt;

	&lt;bean id="bluefishgroup.configurations" parent="webframework.classpathstore"&gt;
		&lt;property name="mustExist"&gt;
			&lt;value&gt;false&lt;/value&gt;
		&lt;/property&gt;
		&lt;property name="classPath"&gt;
			&lt;value&gt;bluefishgroup/site-data/configurations&lt;/value&gt;
		&lt;/property&gt;
	&lt;/bean&gt;

	&lt;bean id="webframework.searchpath.configuration" class="org.alfresco.web.scripts.SearchPath"&gt;
		&lt;property name="searchPath"&gt;
			&lt;list&gt;
				&lt;ref bean="bluefishgroup.configurations" /&gt;
				&lt;ref bean="webframework.remotestore.configuration" /&gt;
				&lt;ref bean="webframework.classpathstore.configuration.custom" /&gt;
				&lt;ref bean="webframework.classpathstore.configuration" /&gt;
			&lt;/list&gt;
		&lt;/property&gt;
	&lt;/bean&gt;

	&lt;!-- Content associations search path overrides --&gt;

	&lt;bean id="bluefishgroup.contentAssociations" parent="webframework.classpathstore"&gt;
		&lt;property name="mustExist"&gt;
			&lt;value&gt;false&lt;/value&gt;
		&lt;/property&gt;
		&lt;property name="classPath"&gt;
			&lt;value&gt;bluefishgroup/site-data/configurations&lt;/value&gt;
		&lt;/property&gt;
	&lt;/bean&gt;

	&lt;bean id="webframework.searchpath.contentassociation" class="org.alfresco.web.scripts.SearchPath"&gt;
		&lt;property name="searchPath"&gt;
			&lt;list&gt;
				&lt;ref bean="bluefishgroup.contentAssociations" /&gt;
				&lt;ref bean="webframework.remotestore.contentassociation" /&gt;
				&lt;ref bean="webframework.classpathstore.contentassociation.custom" /&gt;
				&lt;ref bean="webframework.classpathstore.contentassociation" /&gt;
			&lt;/list&gt;
		&lt;/property&gt;
	&lt;/bean&gt;

	&lt;!-- Page search path overrides --&gt;

	&lt;bean id="bluefishgroup.pages" parent="webframework.classpathstore"&gt;
		&lt;property name="mustExist"&gt;
			&lt;value&gt;true&lt;/value&gt;
		&lt;/property&gt;
		&lt;property name="classPath"&gt;
			&lt;value&gt;bluefishgroup/site-data/pages&lt;/value&gt;
		&lt;/property&gt;
	&lt;/bean&gt;

	&lt;bean id="webframework.searchpath.page" class="org.alfresco.web.scripts.SearchPath"&gt;
		&lt;property name="searchPath"&gt;
			&lt;list&gt;
				&lt;ref bean="bluefishgroup.pages" /&gt;
				&lt;ref bean="webframework.remotestore.page" /&gt;
				&lt;ref bean="webframework.classpathstore.page.custom" /&gt;
				&lt;ref bean="webframework.classpathstore.page" /&gt;
			&lt;/list&gt;
		&lt;/property&gt;
	&lt;/bean&gt;

	&lt;!-- Page association search path overrides --&gt;

	&lt;bean id="bluefishgroup.pageAssociations" parent="webframework.classpathstore"&gt;
		&lt;property name="mustExist"&gt;
			&lt;value&gt;true&lt;/value&gt;
		&lt;/property&gt;
		&lt;property name="classPath"&gt;
			&lt;value&gt;bluefishgroup/site-data/pages&lt;/value&gt;
		&lt;/property&gt;
	&lt;/bean&gt;

	&lt;bean id="webframework.searchpath.pageassociation" class="org.alfresco.web.scripts.SearchPath"&gt;
		&lt;property name="searchPath"&gt;
			&lt;list&gt;
				&lt;ref bean="bluefishgroup.pageAssociations" /&gt;
				&lt;ref bean="webframework.remotestore.pageassociation" /&gt;
				&lt;ref bean="webframework.classpathstore.pageassociation.custom" /&gt;
				&lt;ref bean="webframework.classpathstore.pageassociation" /&gt;
			&lt;/list&gt;
		&lt;/property&gt;
	&lt;/bean&gt;

	&lt;!-- Page type search path overrides --&gt;

	&lt;bean id="bluefishgroup.pageTypes" parent="webframework.classpathstore"&gt;
		&lt;property name="mustExist"&gt;
			&lt;value&gt;false&lt;/value&gt;
		&lt;/property&gt;
		&lt;property name="classPath"&gt;
			&lt;value&gt;bluefishgroup/site-data/pages&lt;/value&gt;
		&lt;/property&gt;
	&lt;/bean&gt;

	&lt;bean id="webframework.searchpath.pagetype" class="org.alfresco.web.scripts.SearchPath"&gt;
		&lt;property name="searchPath"&gt;
			&lt;list&gt;
				&lt;ref bean="bluefishgroup.pageTypes" /&gt;
				&lt;ref bean="webframework.remotestore.pagetype" /&gt;
				&lt;ref bean="webframework.classpathstore.pagetype.custom" /&gt;
				&lt;ref bean="webframework.classpathstore.pagetype" /&gt;
			&lt;/list&gt;
		&lt;/property&gt;
	&lt;/bean&gt;


	&lt;!-- Presets search path overrides --&gt;

	&lt;bean id="bluefishgroup.presets" class="org.alfresco.web.scripts.ClassPathStore"&gt;
		&lt;property name="mustExist"&gt;
			&lt;value&gt;false&lt;/value&gt;
		&lt;/property&gt;
		&lt;property name="classPath"&gt;
			&lt;value&gt;bluefishgroup/site-data/presets&lt;/value&gt;
		&lt;/property&gt;
	&lt;/bean&gt;

	&lt;bean id="webframework.presets.searchpath" class="org.alfresco.web.scripts.SearchPath"&gt;
		&lt;property name="searchPath"&gt;
			&lt;list&gt;
				&lt;ref bean="bluefishgroup.presets" /&gt;
				&lt;ref bean="webframework.classpathstore.presets.custom" /&gt;
				&lt;ref bean="webframework.classpathstore.presets" /&gt;
			&lt;/list&gt;
		&lt;/property&gt;
	&lt;/bean&gt;

	&lt;!-- Templates search path overrides --&gt;

	&lt;bean id="bluefishgroup.templates" parent="webframework.classpathstore"&gt;
		&lt;property name="mustExist"&gt;
			&lt;value&gt;false&lt;/value&gt;
		&lt;/property&gt;
		&lt;property name="classPath"&gt;
			&lt;value&gt;bluefishgroup/templates&lt;/value&gt;
		&lt;/property&gt;
	&lt;/bean&gt;

	&lt;bean id="webframework.templates.searchpath" class="org.alfresco.web.scripts.SearchPath"&gt;
		&lt;property name="searchPath"&gt;
			&lt;list&gt;
				&lt;ref bean="bluefishgroup.webscripts" /&gt;
				&lt;ref bean="bluefishgroup.templates" /&gt;
				&lt;ref bean="webframework.store.templates.custom" /&gt;
				&lt;ref bean="webframework.store.webscripts.custom" /&gt;
				&lt;ref bean="webframework.store.templates" /&gt;
				&lt;ref bean="webframework.store.webscripts" /&gt;
				&lt;ref bean="webframework.store.system-templates" /&gt;
			&lt;/list&gt;
		&lt;/property&gt;
	&lt;/bean&gt;

	&lt;!-- Template instances search path overrides --&gt;

	&lt;bean id="bluefishgroup.templateInstances" parent="webframework.classpathstore"&gt;
		&lt;property name="mustExist"&gt;
			&lt;value&gt;false&lt;/value&gt;
		&lt;/property&gt;
		&lt;property name="classPath"&gt;
			&lt;value&gt;bluefishgroup/site-data/template-instances&lt;/value&gt;
		&lt;/property&gt;
	&lt;/bean&gt;

	&lt;bean id="webframework.searchpath.templateinstance" class="org.alfresco.web.scripts.SearchPath"&gt;
		&lt;property name="searchPath"&gt;
			&lt;list&gt;
				&lt;ref bean="bluefishgroup.templateInstances" /&gt;
				&lt;ref bean="webframework.classpathstore.templateinstance.custom" /&gt;
				&lt;ref bean="webframework.classpathstore.templateinstance" /&gt;
			&lt;/list&gt;
		&lt;/property&gt;
	&lt;/bean&gt;

	&lt;!-- Template types search path overrides --&gt;

	&lt;bean id="bluefishgroup.templateTypes" parent="webframework.classpathstore"&gt;
		&lt;property name="mustExist"&gt;
			&lt;value&gt;false&lt;/value&gt;
		&lt;/property&gt;
		&lt;property name="classPath"&gt;
			&lt;value&gt;bluefishgroup/site-data/template-types&lt;/value&gt;
		&lt;/property&gt;
	&lt;/bean&gt;

	&lt;bean id="webframework.searchpath.templatetype" class="org.alfresco.web.scripts.SearchPath"&gt;
		&lt;property name="searchPath"&gt;
			&lt;list&gt;
				&lt;ref bean="bluefishgroup.templateTypes" /&gt;
				&lt;ref bean="webframework.remotestore.templatetype" /&gt;
				&lt;ref bean="webframework.classpathstore.templatetype.custom" /&gt;
				&lt;ref bean="webframework.classpathstore.templatetype" /&gt;
			&lt;/list&gt;
		&lt;/property&gt;
	&lt;/bean&gt;

	&lt;!-- Template processor search path overrides --&gt;
	&lt;!--
		We need to set these to ensure that the template processors can find
		our web scripts.
     --&gt;

	&lt;bean id="webframework.webscripts.templateprocessor" class="org.alfresco.web.scripts.PresentationTemplateProcessor"&gt;
		&lt;property name="searchPath" ref="webframework.searchpath" /&gt;
		&lt;property name="updateDelay"&gt;
			&lt;value&gt;0&lt;/value&gt;
		&lt;/property&gt;
		&lt;property name="defaultEncoding"&gt;
			&lt;value&gt;UTF-8&lt;/value&gt;
		&lt;/property&gt;
	&lt;/bean&gt;

	&lt;bean id="webframework.templateprocessor" class="org.alfresco.web.scripts.PresentationTemplateProcessor"&gt;
		&lt;property name="searchPath" ref="webframework.templates.searchpath" /&gt;
		&lt;property name="defaultEncoding"&gt;
			&lt;value&gt;UTF-8&lt;/value&gt;
		&lt;/property&gt;
		&lt;property name="updateDelay"&gt;
			&lt;value&gt;0&lt;/value&gt;
		&lt;/property&gt;
	&lt;/bean&gt;

	&lt;!-- Theme search path overrides --&gt;

	&lt;bean id="bluefishgroup.themes" parent="webframework.classpathstore"&gt;
		&lt;property name="mustExist"&gt;
			&lt;value&gt;false&lt;/value&gt;
		&lt;/property&gt;
		&lt;property name="classPath"&gt;
			&lt;value&gt;bluefishgroup/themes&lt;/value&gt;
		&lt;/property&gt;
	&lt;/bean&gt;

	&lt;bean id="webframework.searchpath.theme" class="org.alfresco.web.scripts.SearchPath"&gt;
		&lt;property name="searchPath"&gt;
			&lt;list&gt;
				&lt;ref bean="bluefishgroup.themes" /&gt;
				&lt;ref bean="webframework.remotestore.theme" /&gt;
				&lt;ref bean="webframework.classpathstore.theme.custom" /&gt;
				&lt;ref bean="webframework.classpathstore.theme" /&gt;
			&lt;/list&gt;
		&lt;/property&gt;
	&lt;/bean&gt;

	&lt;!-- WebScripts search path overrides --&gt;

	&lt;bean id="bluefishgroup.webscripts" class="org.alfresco.web.scripts.ClassPathStore"&gt;
		&lt;property name="mustExist"&gt;
			&lt;value&gt;false&lt;/value&gt;
		&lt;/property&gt;
		&lt;property name="classPath"&gt;
			&lt;value&gt;bluefishgroup/site-webscripts&lt;/value&gt;
		&lt;/property&gt;
	&lt;/bean&gt;

	&lt;bean id="webframework.searchpath" class="org.alfresco.web.scripts.SearchPath"&gt;
		&lt;property name="searchPath"&gt;
			&lt;list&gt;
				&lt;ref bean="bluefishgroup.webscripts" /&gt;
				&lt;ref bean="webframework.store.webscripts.custom" /&gt;
				&lt;ref bean="webframework.store.webscripts" /&gt;
				&lt;ref bean="webscripts.store" /&gt;
			&lt;/list&gt;
		&lt;/property&gt;
	&lt;/bean&gt;

&lt;/beans&gt;
</code>
        </pre>
</p>
<h3>
        <a name="head4" class="section">Caveats</a><br />
    </h3>
<p>Although I recommend taking the above steps to enable flexible<br />
			organization of your source, there are a couple things you should<br />
			watch out for.</p>
<p>The first caveat is common to most Spring-based applications.<br />
			Because you are overriding existing configuration elements (as<br />
			opposed to extending), you may run into forward compatibility issues<br />
			when you upgrade to a newer version/build of Alfresco. To stay on top<br />
			of this, make it a habit to always examine the source of those<br />
			configurations you override each time you update your Alfresco<br />
			source. If something changes, simply copy the new element into your<br />
			custom configuration file and reinsert your custom bean reference(s).
		</p>
<p>The second caveat is that it is not always best for all resources<br />
			to be resolved from the classpath. While this may be the most<br />
			straightforward way to deploy resources (because you can easily see<br />
			them within your file system) you can run into consistency problems<br />
			if you need to maintain these resources across multiple web<br />
			applications (as in a clustered environment). In those cases, you<br />
			should consider distributing your resources via the Alfresco<br />
			repository itself. You can do this by using instances of the<br />
			<code>webframework.remotestore</code> bean. Alfresco already does this for a<br />
			handful of resources (search the XML files in the Alfresco source for<br />
			instances of <code>webframework.remotestore.component</code> for an example), and<br />
			it should be straightforward to add repository lookup capability for<br />
			other resources by creating new beans in your Spring configuration.
		</p>
<h3>
        <a name="head5" class="section">Parting Thoughts</a><br />
    </h3>
<p>I like sharing my Alfresco development experiences so that others<br />
			may be able to build upon them to continuously improve the quality of<br />
			contributions to the Alfresco ecosystem. Along those lines, I hope<br />
			you&rsquo;ve found this article helpful, and I encourage you to ask<br />
			questions or leave feedback by adding a comment below. Thanks for<br />
			reading!</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2010/painless-alfresco-development-source-code-organization/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Blue Fish Hosting Alfresco Lunch &amp; Learn Wed. Jan 27</title>
		<link>http://www.bluefishgroup.com/2010/blue-fish-hosting-alfresco-lunch-learn-wed-jan-27/</link>
		<comments>http://www.bluefishgroup.com/2010/blue-fish-hosting-alfresco-lunch-learn-wed-jan-27/#comments</comments>
		<pubDate>Thu, 07 Jan 2010 18:47:01 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=412</guid>
		<description><![CDATA[To help ring in the new year and help folks understand some of the benefits of Alfresco&#8217;s latest Enterprise release, Blue Fish is hosting a Lunch and Learn session at our Austin offices on Jan 27th. This session is a must for CIOs, Senior IT Managers, Enterprise Architects and anyone evaluating ECM solutions. We will [...]]]></description>
				<content:encoded><![CDATA[<p>To help ring in the new year and help folks understand some of the benefits of Alfresco&#8217;s latest Enterprise release, Blue Fish is hosting a Lunch and Learn session at our Austin offices on Jan 27th.</p>
<p>This session is a must for CIOs, Senior IT Managers, Enterprise Architects and anyone evaluating ECM solutions. We will cover the following topics:</p>
<ul>
<li>A comparison of Alfresco Community, Alfresco Enterprise, and Traditional ECM </li>
<li>A review of Alfresco Enterprise 3.2 </li>
<li>Alfresco implementation Best Practices </li>
</ul>
<p><strong>Space is limited to 25 people</strong>, so book your place as soon as possible. Click here to <a href="http://www.alfresco.com/about/events/2010/01/alfresco-lunch-and-learns/register/index/index.jsp">register for the Alfresco lunch and learn</a> session.</p>
<p>The session will last 2 hours, from 11am – 1pm, and of course we&#8217;ll provide lunch. Blue Fish is located in Downtown Austin &#8211; here&#8217;s a <a href="http://www.bluefishgroup.com/about/contact.php">map to the Blue Fish office</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2010/blue-fish-hosting-alfresco-lunch-learn-wed-jan-27/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Webinar: Streamlining Project Management and Team Communication with Alfresco Share 3.2</title>
		<link>http://www.bluefishgroup.com/2009/webinar-streamlining-project-management-and-team-communication-with-alfresco-share-3-2/</link>
		<comments>http://www.bluefishgroup.com/2009/webinar-streamlining-project-management-and-team-communication-with-alfresco-share-3-2/#comments</comments>
		<pubDate>Tue, 25 Aug 2009 20:26:06 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Webinars]]></category>
		<category><![CDATA[Alfresco]]></category>
		<category><![CDATA[alfresco share]]></category>
		<category><![CDATA[Alfresco Share 3.2]]></category>
		<category><![CDATA[project management]]></category>

		<guid isPermaLink="false">http://bluefishgroup.wpengine.com/?p=791</guid>
		<description><![CDATA[See how one company, Blue Fish Development Group, had been delivering projects before Alfresco Share then get a glimpse into how they are now using Share with a few sample use cases. Join us for a case study on how Blue Fish used Alfresco Share. With Josh Toub, General Manager and Josh McJilton, Project Manager [...]]]></description>
				<content:encoded><![CDATA[<p>See how one company, Blue Fish Development Group, had been delivering projects before Alfresco Share then get a glimpse into how they are now using Share with a few sample use cases.<br />
<br />
Join us for a case study on how Blue Fish used Alfresco Share.<br />
<br />
With Josh Toub, General Manager and Josh McJilton, Project Manager &#8211; Blue Fish Development Group<br />
<br />
<a title="Streamlining Project Management and Team Communication with Alfresco Share 3.2" href="https://alfresco.webex.com/alfresco/lsr.php?AT=pb&#038;SP=TC&#038;rID=40819367&#038;act=pb&#038;rKey=a7baec6752a11f44"_blank">Download now!</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2009/webinar-streamlining-project-management-and-team-communication-with-alfresco-share-3-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CenterStage Featured on CMSWire</title>
		<link>http://www.bluefishgroup.com/2009/centerstage-featured-on-cmswire/</link>
		<comments>http://www.bluefishgroup.com/2009/centerstage-featured-on-cmswire/#comments</comments>
		<pubDate>Tue, 25 Aug 2009 11:43:40 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=411</guid>
		<description><![CDATA[There&#8217;s a nice article on CenterStage over at CMSWire. It&#8217;s got several screenshots and a good overview of the features. CenterStage is EMC&#8217;s replacement for eRoom and they are hoping it will help reduce the number of customers who are defecting to SharePoint. I&#8217;ve seen CenterStage at EMC World, and I was impressed. EMC isn&#8217;t [...]]]></description>
				<content:encoded><![CDATA[<p>There&#8217;s a nice <a href="http://www.cmswire.com/cms/enterprise-20/centerstage-how-emc-is-taking-on-microsoft-sharepoint-005310.php">article on CenterStage over at CMSWire</a>. It&#8217;s got several screenshots and a good overview of the features. CenterStage is EMC&#8217;s replacement for eRoom and they are hoping it will help reduce the number of customers who are defecting to SharePoint. I&#8217;ve seen CenterStage at EMC World, and I was impressed. EMC isn&#8217;t known for creating the best UIs and front ends (they are more well known for scalability and their solid back end), but CenterStage has a lot of features I like better than SharePoint.</p>
<p>Read it at <a href="http://www.cmswire.com/cms/enterprise-20/centerstage-how-emc-is-taking-on-microsoft-sharepoint-005310.php">http://www.cmswire.com/cms/enterprise-20/centerstage-how-emc-is-taking-on-microsoft-sharepoint-005310.php</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2009/centerstage-featured-on-cmswire/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Documentum Blog Roundup</title>
		<link>http://www.bluefishgroup.com/2009/documentum-blog-roundup/</link>
		<comments>http://www.bluefishgroup.com/2009/documentum-blog-roundup/#comments</comments>
		<pubDate>Fri, 17 Jul 2009 15:01:19 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=395</guid>
		<description><![CDATA[The Documentum blogging community has really grown over the past year or so. There are lots of people writing about Documentum these days, and there&#8217;s never been more perspectives on what&#8217;s happening with the technology and with EMC&#8217;s Content Management and Archiving group. Here&#8217;s a list of the Documentum-related blogs I read regularly. Craig&#8217;s Musings [...]]]></description>
				<content:encoded><![CDATA[<p>The Documentum blogging community has really grown over the past year or so. There are lots of people writing about Documentum these days, and there&#8217;s never been more perspectives on what&#8217;s happening with the technology and with EMC&#8217;s Content Management and Archiving group.</p>
<p>Here&#8217;s a list of the Documentum-related blogs I read regularly. </p>
<ul>
<li><a href="http://craigrandall.net/">Craig&#8217;s Musings</a> &#8211; I first met Craig Randall at a Documentum conference about a million years ago. At that time, Craig was the king of Documentum&#8217;s Desktop Client and guru of their Microsoft technology strategy. Today, he&#8217;s one of EMC&#8217;s biggest brains and one of their best bloggers. I read everything he writes.</li>
<li><a href="http://johnnygee.wordpress.com/" title="Ask Johnny! &#8211; Documentum Guru">Ask Johnny!</a> &#8211; I think everyone in the Documentum community knows about Johnny Gee. He&#8217;s the most prolific member of the community that I know, answering more questions on dm_developer and EMC&#8217;s forums and everyone else combined. Johnny is a great guy and has been around for years &#8211; he really knows his stuff. Johnny doesn&#8217;t blog that much anymore, but his archives are full of great content.</li>
<li><a href="http://wordofpie.com/" title="Word of Pie">Word of Pie</a> &#8211; Pie is one of the most prolific bloggers in the Documentum blogosphere. His posts range from technical how-to articles to opinion pieces and book reviews. Along with Big Men on Content, he&#8217;s one of the few bloggers that really expresses an opinion. I like that.</li>
<li><a href="http://bigmenoncontent.com/" title="Big Men On Content">Big Men on Content</a> &#8211; Run by Lee Dallas and Marko Sillanpaa, this blog covers Documentum and the broader ECM industry as well. I&#8217;ve known Lee for over ten years, and I&#8217;ve always enjoyed his opinions.</li>
<li><a href="http://paulcwarren.wordpress.com/" title="Paul Warren">Paul Warren</a> &#8211; Paul is an EMC developer focused (I think) on Documentum Composer. His blog posts are typically technical and very useful.</li>
<li><a href="http://www.brilliantleap.com/blog/" title="Brilliant Leap">Brilliant Leap</a> &#8211; This is the blog for Selective Search, a recruiting agency run by Virginia Backaitis, who has been a member of the Documentum community for (I&#8217;m guessing here) more than 10 years. I&#8217;ve know her for 7 or 8 years at least. This blog is not technical, and it focuses mostly on EMC&#8217;s sales and marketing strategies and tactics.</li>
<li><a href="http://ecmobservations.wordpress.com/" title="Observing Content Management">Observing Content Management</a> &#8211; Lee Smith is not a frequent blogger, but when he does, he speaks about his personal experiences with Documentum and his thoughts on the industry.</li>
<li><a href="http://nevertalkwhenyoucannod.typepad.com/" title="Never Talk When You Can Nod">Never Talk When You Can Nod</a> &#8211; Andrew Chapman is the GM of the SharePoint Technologies Group for EMC&#8217;s CMA group. We&#8217;ve been friends for several years, I think, and Andrew is really a super great guy. His blog mostly covers topics related to how SharePoint integrates with Documentum.</li>
<li><a href="http://donr7n.wordpress.com/" title="Say Scheveningen">Say Scheveningen</a> &#8211; This is Don Robertson&#8217;s blog full of Documentum technical tips. Really good stuff in here.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2009/documentum-blog-roundup/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>John Newton Interviewed on Scobleizer</title>
		<link>http://www.bluefishgroup.com/2009/john-newton-interviewed-on-scobleizer/</link>
		<comments>http://www.bluefishgroup.com/2009/john-newton-interviewed-on-scobleizer/#comments</comments>
		<pubDate>Thu, 16 Jul 2009 22:47:35 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=409</guid>
		<description><![CDATA[Robert Scoble interviewed John Newton recently about Alfresco. Two things about the interview stood out to me: Scoble had an idea of what Alfresco was, and he sort of inserted that into John Newton&#8217;s mouth. I wouldn&#8217;t describe Alfresco Share the way that John did, and it was clear to me that he was using [...]]]></description>
				<content:encoded><![CDATA[<p><a href="http://www.kyte.tv/ch/6118/501911">Robert Scoble interviewed John Newton</a> recently about Alfresco. Two things about the interview stood out to me:</p>
<ol>
<li>Scoble had an idea of what Alfresco was, and he sort of inserted that into John Newton&#8217;s mouth. I wouldn&#8217;t describe Alfresco Share the way that John did, and it was clear to me that he was using Scoble&#8217;s language for Scoble&#8217;s benefit. I&#8217;m not sure that it turned out to be a very compelling or accurate description of Alfresco.</li>
<li>It&#8217;s clear that Scoble is focused more on Internet and Web 2.0 technologies than he is commercial/enterprise technologies like Alfresco. His questions and comments would have made more sense if Aflresco was a Web site rather than the enterprise software that it is.</li>
</ol>
<p>At any rate, you get to see John Newton talking about Alfresco, which is always a good thing.</p>
<p>Watch the video here: <a href="http://www.kyte.tv/ch/6118/501911">Alfresco Enterprise Content Management</a> on Scobelizer.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2009/john-newton-interviewed-on-scobleizer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>John Newton on Alfresco Community Edition 3.2</title>
		<link>http://www.bluefishgroup.com/2009/john-newton-on-alfresco-community-edition-32/</link>
		<comments>http://www.bluefishgroup.com/2009/john-newton-on-alfresco-community-edition-32/#comments</comments>
		<pubDate>Thu, 16 Jul 2009 21:00:37 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=408</guid>
		<description><![CDATA[John Newton, founder of Alfresco, has a great description of the just-released Alfresco Community Edition 3.2. In it, he makes the case that recessions like the one we are in are drivers for disruptive technologies, and he sees Alfresco as disruptive in the ECM market because it costs about 5% of traditional ECM platforms. Some [...]]]></description>
				<content:encoded><![CDATA[<p>John Newton, founder of Alfresco, has a great <a href="http://newton.typepad.com/content/2009/07/new-alfresco-32-was-designed-for-the-credit-crunch.html" title="Content Log: New Alfresco 3.2 was designed for the Great Recession">description of the just-released Alfresco Community Edition 3.2</a>. In it, he makes the case that recessions like the one we are in are drivers for disruptive technologies, and he sees Alfresco as disruptive in the ECM market because it costs about 5% of traditional ECM platforms.</p>
<p>Some of the new capabilities in Alfresco 3.2 are</p>
<ul>
<li>Records Management</li>
<li>Improved Capabilities in Share (Alfresco&#8217;s collaboration application), including improved use in Extranet environments</li>
<li>Email Archiving via the IMAP email protocol</li>
<li>iPhone Interface for Share</li>
<li>Improved Capabilities in Deploying Large WCM Solutions</li>
<li></li>
</ul>
<p>John&#8217;s post is chock-full of information about Alfresco 3.2, and I highly recommend taking a look at it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2009/john-newton-on-alfresco-community-edition-32/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Blue Fish is Now an Alfresco Partner</title>
		<link>http://www.bluefishgroup.com/2009/blue-fish-is-now-an-alfresco-partner/</link>
		<comments>http://www.bluefishgroup.com/2009/blue-fish-is-now-an-alfresco-partner/#comments</comments>
		<pubDate>Thu, 16 Jul 2009 14:43:58 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=407</guid>
		<description><![CDATA[I&#8217;m very excited to announce that Blue Fish is now an Alfresco partner. Over the past 4 years, Alfresco has come out of nowhere to take the Enterprise Content Management community by storm. Alfresco has been downloaded over 1.5 MILLION times, and their platform gets better and better with each release. Founded by John Newton, [...]]]></description>
				<content:encoded><![CDATA[<p>I&#8217;m very excited to announce that Blue Fish is now an <a href="http://www.alfresco.com">Alfresco</a> partner. Over the past 4 years, Alfresco has come out of nowhere to take the Enterprise Content Management community by storm. Alfresco has been downloaded over 1.5 MILLION times, and their platform gets better and better with each release.</p>
<p>Founded by John Newton, one of the co-founders of Documentum, Alfresco provides an ECM platform at a price nearly 95% less than a traditional ECM solution. In fact, their standard license is about half of the cost of a traditional ECM vendor&#8217;s yearly maintenance fees. Think about that for a minute &#8211; for about half of what a company is spending on maintenance fees for their existing ECM solution, they can move to a fully supported Alfresco solution. That&#8217;s a very compelling savings.</p>
<h3>Why Alfresco?</h3>
<h4>Alfresco has a Great ROI</h4>
<p>With the current economic climate, our clients are looking for ways to reduce the TCO of their ECM infrastructure. Several of our clients are migrating all or part of their content from expensive traditional ECM platforms (Documentum, FileNet, OpenText) to other platforms that they feel have lower TCO. I&#8217;ve talked to at least three pharmaceutical companies, for example, that are moving part of their content out of Documentum because they feel that it&#8217;s overkill for their needs. The content in question isn&#8217;t regulated and isn&#8217;t used very frequently, and they just can&#8217;t justify the cost of Documentum licenses for it. One of my clients told me, &#8220;It&#8217;s like keeping your Timex watch in a bank vault. That makes sense for a Rolex, but it&#8217;s overkill for a Timex.&#8221; These companies are continuing to use Documentum for their most critical content, but they are using other platforms for less critical content. OSHA, NYPD, Morgan Stanley, and Cisco are just some of the companies that have transitioned from one of the &#8220;Big Three&#8221; ECM vendors to Alfresco.</p>
<h4>Alfresco Broadens Our Market</h4>
<p>Alfresco is a great choice for smaller organizations or departments within larger companies that can&#8217;t justify the expense of a traditional ECM solution, because they don&#8217;t need all the horsepower and don&#8217;t operate at true enterprise scale. Alfresco has been benchmarked at over 100 Million documents, which is orders of magnitude more than most ECM systems are currently managing. By partnering with Alfresco, Blue Fish can take our brand of ECM services to more companies than we have been able to in the past.</p>
<h4>Familiar Technologies</h4>
<p>Alfresco is built using technologies with which we are very familiar. It&#8217;s a Java-based solution, and many of the technologies that are used as the building blocks of Alfresco (Hibernate, Spring, Freemarker, etc.) are technologies Blue Fish has been using in our solutions for years. Because the Alfresco technology stack is so familiar to our developers, it&#8217;s easy to ramp up and adapt our existing products and solutions to Alfresco.</p>
<h3>What about Documentum?</h3>
<p>We still love Documentum, and we still believe that there is a ton of value in using Documentum as your Enterprise Content Management platform. Especially for those huge organizations with really complex content management processes, Documentum is one of the best games in town. The breath and depth of the Documentum platform is staggering, there are hundreds of third-party add-ons and integrations, and they continue to innovate and acquire new technologies that keep them at the top of the pack. If your IT strategy is to invest in a single ECM technology across your entire organization, Documentum is a very good choice.</p>
<p>But more and more companies are moving away from a single ECM platform and are instead deploying a hybrid model with Documentum handling the more elaborate content management tasks and Alfresco taking care of the less complex needs. Also, when a smaller department needs content management, they often can&#8217;t justify the expense of a commercial ECM platform such as Documentum, so they often just make do with a file system. With Alfresco, a company can provide ECM tools to a larger percentage of their knowledge workers than they can with Documentum alone.</p>
<p>We see Documentum and Alfresco as two different types of tools. There are situations where Documentum is going to be the best fit and others where Alfresco is the best fit.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2009/blue-fish-is-now-an-alfresco-partner/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>CenterStage &#8211; EMC&#8217;s Next Generation Collaboration Application</title>
		<link>http://www.bluefishgroup.com/2009/centerstage-emcs-next-generation-collaboration-application/</link>
		<comments>http://www.bluefishgroup.com/2009/centerstage-emcs-next-generation-collaboration-application/#comments</comments>
		<pubDate>Thu, 21 May 2009 16:54:02 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=406</guid>
		<description><![CDATA[What I learned about CenterStage at EMC World 2009 CenterStage was all the rage this year at EMC World, and it looks like it&#8217;s eventually going to be Documentum&#8217;s primary knowledge worker UI. CenterStage replaces eRoom, and it provides a collaboration environment for teams. CenterStage works like this: You define a &#8220;space&#8221;, which is like [...]]]></description>
				<content:encoded><![CDATA[<p><b>What I learned about CenterStage at EMC World 2009</b></p>
<p>CenterStage was all the rage this year at EMC World, and it looks like it&#8217;s eventually going to be Documentum&#8217;s primary knowledge worker UI. CenterStage replaces eRoom, and it provides a collaboration environment for teams. CenterStage works like this: You define a &#8220;space&#8221;, which is like a room in eRoom &#8211; it&#8217;s a collection of documents, discussion threads, wiki pages, blogs, etc. all related to a single project or a single team. You can invite users to become members of this space, and then they can organize all their information about that project together in one place. The concept of spaces or rooms is not new &#8211; SharePoint, Alfresco, and several others use this same paradigm.</p>
<p>CenterStage is pretty slick looking, and I think it will make a big splash in the Documentum community. The search function is a million times better than WebTop&#8217;s, and with the addition of Blogs, Wikis, and Discussions it&#8217;s much more suited to the way teams share information than WebTop. WebTop and other document management clients are constrained to documents only, and most teams that use WebTop end up sending a ton of emails to each other to share all the information that doesn&#8217;t fit nicely into a document. With CenterStage, a lot of the information that goes into emails could easily transition to CenterStage, being stored in Discussion Groups, on Wiki Pages, as Blog Entries, or (in an upcoming release) as Data Tables (kind of like an online spreadsheet). Not only do your end users benefit from improved collaboration and information sharing, but the organization gets all the traditional compliance benefits that Documentum offers, such as centrally managed retention policies, archiving, eDiscovery, etc.</p>
<p>One of the nice features of CenterStage is the ability to scope your searches. When you issue a search, you can tell CenterStage where to search:</p>
<ul>
<li>Search within your current space</li>
<li>Search within all you <i>favorite</i> spaces </li>
<li>Search all the spaces you have access to</li>
<li>Search the entire Documentum repostiory (assuming you are using Documentum for standard document management as well)</li>
<li>Use EMC&#8217;s Federated Search Services to search other repositories, such as FileNet, Wikipedia, etc.</li>
</ul>
<p>Earlier this week, I mistakenly reported that CenterStage was developed using the FLEX interface, but I was wrong. It&#8217;s actually a <a href="http://en.wikipedia.org/wiki/Rich_Internet_application">Rich Internet Application</a> built using a JavaScript framework called <a href="http://extjs.com/products/extjs/">Ext JS</a>. There are a couple of components that utilize FLEX, but it&#8217;s not a FLEX application. Here&#8217;s how CenterStage works. When you load CenterStage for the first time, your browser loads up a ton of fancy JavaScript (the Ext framework). Then, whenever you click on a folder or a document, the browser uses JavaScript to make a call to a DFS Web Service. The result is returned as XML, and Ext then renders that XML as HTML. This is notably different from how WDK applications work. In WDK, a JSP page or Servlet makes a call to Documentum, renders the result as HTML, and then passes that HTML down to the browser. In Ext, there&#8217;s no JSP or Servlet acting as a middleman &#8211; the browser makes the call directly to the web service and then formats the result and writes it into the DOM.</p>
<p>CenterStage will require a new skill set to customize, and there will be fewer customization points than are available in WebTop. The next release of CenterStage has limited extension points, but these will open up over time. Right now, the main customizations are the ability to create new &#8220;widgets&#8221;, little UI controls that can be included on Wiki Pages within CenterStage. These widgets are developed in JavaScript or Flex and make WebService calls to back-end services.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2009/centerstage-emcs-next-generation-collaboration-application/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>EMC World 2009 &#8211; Attack of xDB</title>
		<link>http://www.bluefishgroup.com/2009/emc-world-2009-day-4/</link>
		<comments>http://www.bluefishgroup.com/2009/emc-world-2009-day-4/#comments</comments>
		<pubDate>Thu, 21 May 2009 02:55:43 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=405</guid>
		<description><![CDATA[EMC World 2009 &#8211; Day 4 Recap and Day 5 Plans Today, it seemed like every session that I attended was talking about xDB, EMC&#8217;s high-performance XML database. xDB is the product formerly known as X-Hive/DB, acquired by EMC in 2007. For the past couple of years, EMC has been selling xDB as a stand-alone [...]]]></description>
				<content:encoded><![CDATA[<p><b>EMC World 2009 &#8211; Day 4 Recap and Day 5 Plans</b></p>
<p>Today, it seemed like every session that I attended was talking about xDB, EMC&#8217;s high-performance XML database. xDB is the product formerly known as X-Hive/DB, acquired by EMC in 2007. For the past couple of years, EMC has been selling xDB as a stand-alone product, but at the same time, they were busy integrating it with several of their existing products. But before we talk about that, I should probably bring you up to speed on what an XML database does.</p>
<p>An <a href="http://en.wikipedia.org/wiki/XML_database">XML database</a> is similar to a relational database except that instead of storing structured data in rows and columns, it stores semi-structured data in the form of XML files. xDB allows the use of XQuery to query the database and return chunks of XML, from an entire document (or several documents) to a single element. xDB treats the elements in XML files like the columns of a database.</p>
<p>Documentum has supported XML documents for over 10 years, but xDB brings that support to a whole new level. Take the following scenario, for example. Imagine you have a large XML document, like a product catalog from one of your suppliers. You get the catalog in XML format from your supplier, and you use it to generate pages on your web site that list the products you sell.</p>
<p>This scenario poses a challenge. You need to somehow get the data in this XML file into a form that can be displayed on your web site. Your web site is dynamic, with product catalog that can be sorted and searched, so you need to be able to query for individual products. What you need is a list of products, but all you have right now is a giant XML file with a &lt;product&gt; tag delineating each product. </p>
<p>In the past, to deal with this scenario, you would create an XML Application &#8211; a set of rules for processing the XML when it is imported into the repository. Your XML application would do two main things: first, it would &#8220;chunk&#8221; the XML file into smaller XML files, one for each product. These would all be linked into a virtual document that represented the main XML file. Your XML application would also parse out certain elements of the product (description, price, image URL, etc.) and write the values into metadata attributes on the document object. Now you have a list of product objects in the repository with attribute values that can be searched and displayed in a list. You would then write code on your web site to query the docbase and display your product catalog. </p>
<p>This approach has been used for years, and I used to build applications for the airline industry that used these techniques to manage huge Aircraft Maintenance Manuals. But there are some drawbacks.</p>
<p>First, in order for this to work, you must have a custom object type that contains attributes for all the elements of the XML file that you want to be able to search. That means you have to know which attributes will be displayed on the web site before you start managing your content. That&#8217;s often not the case. Second, you have to have a different object type for each type of product, because you&#8217;ll receive different XML files from different suppliers &#8211; the schemas will be different and the relevant attributes will be different (for one type of product, color may be important while for another product, size is important). Third, if the supplier changes their XML format or adds new properties, you have to update your object model and do it all over again.</p>
<p>With xDB, you don&#8217;t have to do any of this planning or object modeling. xDB can handle any arbitrary XML format, so you just import your document when you receive it from the supplier. And it doesn&#8217;t need to be chunked into smaller files, because xDB can return XML fragments when you query it. In effect, you can ask xDB to return you a list of all the products of type &#8220;Shoe&#8221; where size is &#8220;11&#8243; and color is &#8220;Black&#8221;, and xDB will return a collection of XML fragments, one for each product element that matches that criteria. No chunking or attribute population is required, and there&#8217;s no database design involved, either, because xDB does not need any up-front knowledge of the XML schemas you plan to use. Just import your documents and xDB does the rest.</p>
<p>It turns out that xDB is very fast, very scalable, and has very high performance. It&#8217;s fast to import documents into it, and it&#8217;s fast to query it. I saw a demo today where xDB processed thousands of documents a second on some crappy laptop hardware. Some say that xDB is faster and better than a relational database, not only for hierarchical XML data (which it certainly is), but also for normal structured data. I&#8217;m beginning to think that those people may be right.</p>
<p>EMC has decided to make xDB a huge part of its technology strategy, and xDB is now being integrated and embedded in several applications.</p>
<ul>
<li><b>As Part of the Content Server</b> &#8211; In one of the first major architecture changes to the Content Server since the introduction of the Method Server, Documentum will now contain an embedded instance of xDB where XML documents will be stored. You&#8217;ll be able to combine DQL and XQuery to get access from within Documentum to the features I described above. This is a big deal.</li>
<li><b>As Part of Enterprise Search Services (ESS)</b> &#8211; Documentum is replacing the FAST full-text engine with ESS, and ESS is powered by xDB. You heard me right. For the past several months, they have been adding full-text capabilities to xDB (leveraging Lucene, an open source search engine), and in an upcoming release of Documentum, the embedded full-text engine will be xDB.</li>
<li><b>As Part of Dynamic Delivery Services (DDS)</b> &#8211; DDS is a new product built on top of Interactive Delivery Services (IDS). It allows you to publish your web content into xDB and then query it from your web site. Intel is using this to run their entire Intel.com web site, and I can see how something like this would add lots of power to our web content management solutions while actually simplifying the solution.</li>
</ul>
<p>Tomorrow is the last day of the conference, and I&#8217;m only planning on attending two sessions before I head off to the airport:</p>
<ul>
<li><b>THURSDAY 8:30</b> &#8211; Customer Experience – Web 2.0 and Personalized Customer Communications Product Overview and Strategies</li>
<li><b>THURSDAY 10:00</b> &#8211; CMIS &#8211; Changing the World One Application at a Time</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2009/emc-world-2009-day-4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>EMC World 2009 &#8211; Marketing Teams Get Some Attention</title>
		<link>http://www.bluefishgroup.com/2009/emc-world-2009-day/</link>
		<comments>http://www.bluefishgroup.com/2009/emc-world-2009-day/#comments</comments>
		<pubDate>Wed, 20 May 2009 04:43:12 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=404</guid>
		<description><![CDATA[EMC World 2009 &#8211; Day 3 Recap and Day 4 Plans Today was WCM/DAM day for me here at EMC World. I attended two WCM-related sessions and spent some time down in the Exhibition Hall with the DAM team. Overall, what I learned is good news for marketing teams. EMC is targeting marketing teams by [...]]]></description>
				<content:encoded><![CDATA[<p><b>EMC World 2009 &#8211; Day 3 Recap and Day 4 Plans</b></p>
<p>Today was WCM/DAM day for me here at EMC World. I attended two WCM-related sessions and spent some time down in the Exhibition Hall with the DAM team. Overall, what I learned is good news for marketing teams.</p>
<p>EMC is targeting marketing teams by investing in two of its solution suites: the Web Content Management suite of products and the Digital Asset Management suite of products. The biggest investment, and the most impressive results, seem to have come on the DAM side with big improvements to Media Workspace, EMC&#8217;s next generation DAM client.</p>
<p>Media Workspace was released last year as a simple client for image browsing and annotation. Developed using the FLEX platform, Media Workspace provided a glimpse into EMC&#8217;s future direction in rich web-based clients with a Web 2.0 feel. We evaluated Media Workspace earlier this year, and frankly, it left us scratching our heads. The product didn&#8217;t seem complete &#8211; it had a very limited set of features, and we couldn&#8217;t think of a single real-world scenario where Media Workspace was a better choice than Digital Asset Manager. </p>
<p>Well, I&#8217;m happy to report that all that has changed. In my opinion, the previous version of Media Workspace was released a bit prematurely, but the new version that I saw today looks a thousand times better.</p>
<p>The new version of Media Workspace is a fairly full-featured DAM client. In addition to supporting images (as the previous version did), this version also supports video. It has support for workflows, collections, thumbnails, transformations, ratings, annotations, and all the expected library services (checkin/checkout). I can see how a marketing team could use the product to handle most of their digital asset management use cases, and I think the product really shines if you are managing video. There&#8217;s even a built-in video viewer so that you can preview a video before downloading the high-res rendition. The overall user interface is improved as well &#8211; this version seems a little more polished than the previous version, and I was told that this is one of the advantages of using FLEX &#8211; it&#8217;s easier to update the user interface than it has been with WDK.</p>
<p>So what will become of Digital Asset Manager? It is still required for all the DAM-related administrative use cases, such as setting up transformation rules, and there are probably some power-user use cases where DAM is better than Media Workspace. But it appears that EMC&#8217;s vision is that most marketing users will spend their time in Media Workspace.</p>
<p>The Web Content Management products have seen similar improvements. EMC is releasing a new version of the Contributor UI, a simple client aimed at content authors and reviewers. Like Media Workspace, the new Contributor UI has been developed using the FLEX framework and has a completely new user experience and look and feel. This is a brand new application. Pagebuilder has also seen improvements, and there&#8217;s a new FLEX-based Web Publisher Editor. The Web Publisher Editor is the form that authors fill out to create a piece of content. It&#8217;s previously been a Java Applet, and many people find it difficult to use. The new editor has two interesting new features:</p>
<ul>
<li>A template form can now have multiple tabs, so that instead of the super long form that was required in previous versions, developers can group form fields together on tabs, giving a sort of wizard-like authoring experience. One big advantage of this is that if your page is laid out in &#8220;blocks&#8221;, you can group all the fields for one of those blocks together on their own tab. </li>
<li>A template form can now be laid out horizontally as well as vertically. This means that you can have fields side by side, saving space over the previous version that forced fields to be stacked on top of each other in an endless list.</li>
</ul>
<p>You&#8217;ll be able to call the new editor from within the new Contributor UI, the standard Web Publisher client, and Pagebuilder. All this will be available in version 6.5 SP3, which is scheduled for Q1 2010.
</p>
<p>Other improvements have been made to the WCM Edition&#8217;s publishing capabilities. Site Caching Services (SCS) and Site Delivery Services (SDS) have been renamed and enhanced. The new product, called Interactive Delivery Services (IDS), includes an XML datastore in addition to the relational database that SCS has always provided. Based on the X-Hive product acquired in 2007, this XML datastore provides new options for delivering content to your web properties. Another new feature of IDS is the ability to take user-generated content from your web site (such as ratings or comments) and ingest them back into the Documentum repository. This is done by first writing them into IDS which will then write them into Documentum.</p>
<p>Perhaps the most anticipated improvement that comes with IDS is a completely new architecture for delivering content to a cluster of web servers. SDS has given administrators fits for years, and I can already hear people rejoicing that there is a replacement.</p>
<p>Tomorrow, I&#8217;m planning on attending these sessions:</p>
<ul>
<li><b>WEDNESDAY 8:00</b> &#8211; Beyond EMC Documentum 6.5 &#8211; A Product Roadmap</li>
<li><b>WEDNESDAY 9:30</b> &#8211; EMC Documentum CenterStage &#8211; A Technical Review</li>
<li><b>WEDNESDAY 11:00</b> &#8211; Best Practices for Moving WDK Customizations to EMC Documentum CenterStage and/or Next-Generation Documentum</li>
<li><b>WEDNESDAY 2:45</b> &#8211; Smarten Up Your Content with EMC Documentum XML</li>
<li><b>WEDNESDAY 4:15</b> &#8211; Best Practices for EMC Documentum xDB and XML Dynamic Delivery Services</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2009/emc-world-2009-day/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>EMC World 2009 &#8211; Return of the Son of Momentum</title>
		<link>http://www.bluefishgroup.com/2009/emc-world-2009-day-2/</link>
		<comments>http://www.bluefishgroup.com/2009/emc-world-2009-day-2/#comments</comments>
		<pubDate>Tue, 19 May 2009 02:59:28 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=403</guid>
		<description><![CDATA[EMC World 2009 &#8211; Day 2 Thoughts and Day 3 Plans Today was the first full day of EMC World 2009. As I mentioned earlier, EMC has indeed grouped the Documentum-related topics and partners together, and I think they have successfully pulled off the conference in a conference. I talked to Whitney Tidmarsh, Chief Marketing [...]]]></description>
				<content:encoded><![CDATA[<p><b>EMC World 2009 &#8211; Day 2 Thoughts and Day 3 Plans</b></p>
<p>Today was the first full day of EMC World 2009. As I mentioned earlier, EMC has indeed grouped the Documentum-related topics and partners together, and I think they have successfully pulled off the conference in a conference. I talked to Whitney Tidmarsh, Chief Marketing Officer of EMC&#8217;s Content Management and Archiving Division, and an old friend (I actually trained her on Documentum when she first joined the company 14 years ago). Whitney told me that the &#8220;buying affinity&#8221; of EMC&#8217;s CMA customers was different from that of its hardware customers, and that they finally realized it was best to separate the CMA sessions from the rest of the conference. The best part is that they are calling the conference within a conference &#8220;Momentum&#8221;, which is the name of the old Documentum User Group conference before they were acquired by EMC.</p>
<p>I have to admit that pulling out the Documentum sessions into a little Momentum conference has made a HUGE difference. Whitney told me that there&#8217;s about 800 CMA attendees this year, so that means that only about 11% of the attendees are Documentum focused. You can start to see how we feel a little underappreciated and overwhelmed in the midst of 6,200 hardware focused attendees.</p>
<p>Overall, the sessions I attended today were decent. I didn&#8217;t get to attend most of the ones I targeted due to space limitations. All four of the sessions I wanted to attend had crowds flowing out the door, and I only made it inside the room for two of them. For the other two, I attended my second choice sessions, which were fine.</p>
<p>The best session of the day was John McCormick&#8217;s presentation on Collaborative Technologies.  John is another old friend of mine, and he&#8217;s the GM of Knowledge Worker products, which (if I understand correctly) covers WebTop, CenterStage, and My Documentum. John covered each of these in his presentation, and he&#8217;s so freaking smart and knowledgeable that it&#8217;s a real pleasure to see him present. The biggest discovery for me today was about My Documentum, which is a rebranding and upgrade of some existing Documentum applications.</p>
<p>My Documentum has three components:</p>
<ul>
<li><b>My Documentum Offline</b> &#8211; This is the old Offline Client (available as part of WebTop), and it allows users to synchronize content between their hard drive and the repository. If content in the repository is added or updated, it&#8217;s automatically downloaded to your hard drive, and if you edit one of those files while on a plane, it will automatically check it in as a new version the next time you connect to the network.</li>
<li><b>My Documentum for the Desktop</b> &#8211; This is the old Documentum File Share Services, and it allows you to access Documentum as a shared drive from either a Windows or a Mac desktop.</li>
<li><b>My Documentum for Outlook</b> &#8211; This is a rewrite of the Documentum Client for Outlook. It now operates as a full-featured Documentum client &#8211; you can browse folders, import emails and attachments into Documentum, etc. </li>
</ul>
<p>There&#8217;s a huge push around CenterStage, Documentum&#8217;s new collaboration application launched last year. This application breaks away from the WDK model and employs a FLEX-based development framework. EMC claims that their customers were asking for a more Web 2.0 experience, and the CMA group responded by developing a new set of applications using the FLEX framework from Adobe. I&#8217;m not convinced that this is the best decision, because most Web 2.0 applications are actually HTML and AJAX based, and I&#8217;m sort of tired of EMC changing the development environment every few years. I&#8217;m also worried about how anyone is ever going to effectively customize it. But that&#8217;s probably a point of view best elaborated on in a future post.</p>
<p>CenterStage is breaking some new ground for Documentum, and probably the biggest thing from my perspective is the addition of faceted search refinement. Blue Fish has been adding Faceted Search Refinement to our Documentum solutions for over 4 years, and I think it makes a huge improvement in usability. You can learn more about what Faceted Search Refinement is by watching a <a href="https://admin.acrobat.com/_a63582769/p63859158/">webinar that we recorded with Endeca last year</a>. </p>
<p>The other big push is for SourceOne, EMC&#8217;s new Archiving and Records Management suite. I hope to learn more about that later in the week.
<p>Tomorrow, I plan on attending the following sessions. We&#8217;ll see if I get into any of them. <img src='http://www.bluefishgroup.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<ul>
<li><b>TUESDAY 8:00</b> &#8211; What&#8217;s New with Web Content Management and the Product Vision of Web Experience Management</li>
<li><b>TUESDAY 11:00</b> &#8211; Configure, Don&#8217;t Code! and Other Ways the EMC Documentum Platform is Making it Easier to Build Solutions</li>
<li><b>TUESDAY 2:45</b> &#8211; Federated, Virtual, Universal…Can You Have it All?</li>
<li><b>TUESDAY 4:15</b> &#8211; Customizing EMC Documentum CenterStage 1.0</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2009/emc-world-2009-day-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>EMC World 2009 &#8211; Gin Blossoms Invade</title>
		<link>http://www.bluefishgroup.com/2009/emc-world-2009-day-1/</link>
		<comments>http://www.bluefishgroup.com/2009/emc-world-2009-day-1/#comments</comments>
		<pubDate>Mon, 18 May 2009 12:23:49 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=402</guid>
		<description><![CDATA[EMC World 2009 &#8211; Day 1 Recap and Day 2 Plan I arrived in Orlando last night for the kickoff of EMC World, the big EMC User&#8217;s Conference. EMC tells us that 7,000 people will be attending the conference this year, which is mostly focused on storage technology but also has a healthy amount of [...]]]></description>
				<content:encoded><![CDATA[<p><b>EMC World 2009 &#8211; Day 1 Recap and Day 2 Plan</b></p>
<p>I arrived in Orlando last night for the kickoff of EMC World, the big EMC User&#8217;s Conference. EMC tells us that 7,000 people will be attending the conference this year, which is mostly focused on storage technology but also has a healthy amount of attention paid to enterprise content management. This year, I&#8217;m told that there will be a content management &#8220;conference in a conference&#8221; which amounts to grouping all the content managment sessions together in the same part of the convention center and grouping all the content management vendors together in the same part of the exhibitor&#8217;s hall. The portion of EMC&#8217;s customers that are Documentum-focused have been complaining for the past few years that they get lost in the massive hardware focus that is EMC&#8217;s primary business, so I&#8217;ll let you know if the conference in a conference works well this year.</p>
<p>When I checked in last night, I was immediately struck by the demographics of the attendees. They are probably 90%-95% male (more skewed than other IT conferences I&#8217;ve been to), aged 25-45,  and without a lot of racial diversity. What is it about computer storage that attracts white dudes in their 30s?</p>
<p>Last night&#8217;s event was a concert by the Gin Blossoms. This is a band I know well but haven&#8217;t seen play live before. When I was in college, my band aspired to be just like the Gin Blossoms, and their album New Miserable Experience was in heavy rotation in my dorm room. I&#8217;m a sucker for a great pop-rock song with catchy melodies and harmony vocals, and that&#8217;s the Gin Blossom&#8217;s bread and butter. It was nice to see them play live, but you could tell that their hearts weren&#8217;t in it. Playing for a convention full of IT geeks that are primarily there for the free buffet is a long way from the club full of rabid fans they are used to. The lead singer tried to get the crowd engaged, but the energy was way off. In a normal gig, even if you are playing to only 100 people, it&#8217;s 100 people that stood in line to see you, and the energy of the room reflects that. Last night, there were 2,000 &#8211; 3,000 people at the event, but they were just there for something to do, and it showed in the vibe of the crowd. </p>
<p>I&#8217;m about to head out to the morning sessions. I&#8217;m planning to attend the following, so if you read this and want to find me, you&#8217;ll know where to look. My Monday is going to be all about understanding EMC&#8217;s current &#8220;pitch&#8221;. I&#8217;m pretty up to date on the technologies below, but I&#8217;m always interested in how EMC is packaging them and presenting them to the market.</p>
<p>
<ul>
<li><b>MONDAY 8:30</b> &#8211; Fundamentals: Content Management and Archiving Product Overview</li>
<li><b>MONDAY 11:30</b>  &#8211; What&#8217;s New with the EMC Documentum Platform</li>
<li><b>MONDAY 3:00</b> &#8211; EMC Documentum CenterStage: Bringing Enterprise Content Management to Everyone</li>
<li><b>MONDAY 4:30</b> &#8211; EMC Documentum 6.5 Architecture Overview</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2009/emc-world-2009-day-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New Article: Using Migration Workbench for More than Migrations</title>
		<link>http://www.bluefishgroup.com/2009/new-article-using-migration-workbench-for-more-than-migrations/</link>
		<comments>http://www.bluefishgroup.com/2009/new-article-using-migration-workbench-for-more-than-migrations/#comments</comments>
		<pubDate>Tue, 03 Mar 2009 21:54:25 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=401</guid>
		<description><![CDATA[Pete Nevin, one of our migration experts, just published an article that explores some of the innovative ways our clients have been using Migration Workbench. Although Migration Workbench was designed for content migrations, folks have been using it to archive documents, synchronize repositories, integrate Documentum with SharePoint, and perform a variety of other system administration [...]]]></description>
				<content:encoded><![CDATA[<p>Pete Nevin,  one of our migration experts, just published an article that explores some of the innovative ways our clients have been using Migration Workbench. Although Migration Workbench was designed for content migrations, folks have been using it to archive documents, synchronize repositories, integrate Documentum with SharePoint, and perform a variety of other system administration and integration tasks.</p>
<p>Learn more by reading <a href="/library/2009/mwb-additional-uses/">Using Migration Workbench for More than Migrations</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2009/new-article-using-migration-workbench-for-more-than-migrations/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New Article: Web Publisher Technical Architecture: A Primer</title>
		<link>http://www.bluefishgroup.com/2009/new-article-web-publisher-technical-architecture-a-primer/</link>
		<comments>http://www.bluefishgroup.com/2009/new-article-web-publisher-technical-architecture-a-primer/#comments</comments>
		<pubDate>Tue, 03 Mar 2009 21:49:00 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=400</guid>
		<description><![CDATA[Nichole DuBose recently published a technical overview of the Architecture of Documentum&#8217;s Web Publisher solution. When you deploy Web Publisher, it&#8217;s surprising how many components you need to set up and configure. There are databases, multiple application servers and web servers, and several pieces of Documentum software that have specialized purposes. Nicki&#8217;s article does a [...]]]></description>
				<content:encoded><![CDATA[<p>Nichole DuBose recently published a technical overview of the <a href="/library/2009/web-publisher-technical-architecture-a-primer/">Architecture of Documentum&#8217;s Web Publisher</a> solution. When you deploy Web Publisher, it&#8217;s surprising how many components you need to set up and configure. There are databases, multiple application servers and web servers, and several pieces of Documentum software that have specialized purposes. Nicki&#8217;s article does a great job of explaining all these pieces and how they fit together. </p>
<p>Check out <a href="/library/2009/web-publisher-technical-architecture-a-primer/">Web Publisher Technical Architecture: A Primer</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2009/new-article-web-publisher-technical-architecture-a-primer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using Migration Workbench for More Than Migrations</title>
		<link>http://www.bluefishgroup.com/2009/mwb-additional-uses/</link>
		<comments>http://www.bluefishgroup.com/2009/mwb-additional-uses/#comments</comments>
		<pubDate>Tue, 03 Mar 2009 12:00:00 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Content Migrations]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=399</guid>
		<description><![CDATA[Introduction With the release of Migration Workbench&#8482;, Blue Fish has changed the way we perform content migrations projects. Key new capabilities such as true incremental re-processing of changes, dynamic cutover, rules-based transformations, and live-to-live migrations have dramatically reduced the time and cost of even the most complex migrations. But our clients aren&#8217;t stopping there. These [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Introduction</a><br />
    </h3>
<p>With the release of Migration Workbench&trade;, Blue Fish has changed the way we perform content migrations projects.  Key new capabilities such as <strong>true incremental re-processing</strong> of changes, <strong>dynamic cutover</strong>, <strong>rules-based transformations</strong>, and <strong>live-to-live migrations</strong> have dramatically reduced the time and cost of even the most complex migrations.</p>
<p>But our clients aren&rsquo;t stopping there.  These new capabilities are being used to solve a variety of content management challenges across the enterprise.</p>
<h3>
        <a name="head2" class="section">Use Cases</a><br />
    </h3>
<h4>Bulk Archiving</h4>
<p>There is a common need for owners of Content Management Systems (CMS) to archive documents.  This need may arise from the need to comply with records management policies, or as part of a larger consolidation project.  Mergers and divestitures may also require the bulk archiving of content.  Some types of CMS perform better when object counts are kept low, and so archiving older versions of documents can help to improve system performance.</p>
<p>Generally this task is performed manually by system administrators, and often using very blunt tools.  A common practice is to use a tool that specifies the documents to be removed by query.  The administrator then exports the documents to an archive system and deletes them from the source system.</p>
<p>In order to archive a particular piece of content and not another similar object, you need to be able to identify it with a specific query.  This does not provide the level of granularity often needed to select all the documents, and only the documents, to be archived.  If the archive system is on another platform, an entirely new approach must also be found to load and verify the archived data.  The result is often a large amount of custom programming requiring a high level of expertise to operate and maintain.</p>
<p>Applying Migration Workbench to this task, even very complex archiving requirements can be quickly configured as migration rules.  For example, you may wish to archive documents that meet the following characteristics:</p>
<ul>
<li>located in a specific folder,</li>
<li>older than a certain date,</li>
<li>inactive for greater than a year,</li>
<li>having version numbers less than the current major version,</li>
<li>only moving the original document to the archive, and</li>
<li>deleting all pdf renditions from the source.</li>
</ul>
<p>Using Migration Workbench, writing these requirements as migration rules is easy!  First, list the folder as the batch criteria for documents that are candidates for archive.  Next, write simple rules to identify 1) documents created since the cutoff date, 2) active documents, 3) documents inactive for less than a year, and 4) current documents.  Indicate that these documents are not to be migrated. The remaining documents are those to be archived.  The last step is to write a rule to only copy over the original document and not renditions.  Migration Workbench takes care of the rest.</p>
<p>Because migration and cutover are two separate activities in Migration Workbench, the user can also preview the documents to be archived prior to making the move permanent.  Migration Workbench provides reports that detail exactly which documents are in what state.  And using the incremental migration approach, mistakes can be quickly and easily rectified by simply changing the rules and rerunning the tool.</p>
<div align="center">
        <img src="/article-assets/images/mwb-additional-uses/archive.jpg" border="0" alt="Fig. 1: Graphic of Archiving Documents">
<p class="figure">
            <b><br />
              Figure 1:<br />
            </b> Using Migration Workbench to Perform System Archiving</p>
</p></div>
<h4>Continuous Archiving</h4>
<p>Many users want a way to move old or obsolete documents from their CMS to an archive on an ongoing basis.  The criteria for moving documents into archive may be based on metadata values such as document age or document status, or it may be based on a user actively selecting to archive the document.  This need is very similar to bulk archiving, but is a continual archiving process rather than a big bang event.</p>
<p>As with bulk archiving, Migration Workbench can be configured with migration rules to correctly identify, move, and cut over content to the archive.  However, you can also take advantage of the incremental processing capabilities of Migration Workbench to create a continual archiving process.  By setting Migration Workbench to run on regular intervals, it effectively monitors the CMS for changes to content or metadata that qualifies that content for archiving.  System administrators can easily see and audit the results of this process using standard Migration Workbench reporting.</p>
<h4>Publishing Content for Broad Consumption</h4>
<p>Many organizations maintain separate content management systems for the authoring and publishing of content.  The two systems are frequently built on two different repositories, or even on two different content management platforms.  As an example, one recent Blue Fish client wanted a one-way publishing solution to push finished documents from their authoring system, hosted on Documentum, to a read-only system used for distributing training documents and SOPs, hosted on their portal platform, Sharepoint.  The authoring system contained all the rich content creation, editing, and workflow of Documentum, but was only accessible to a small subset of content authors.  The read-only system was hosted on Sharepoint, reducing the need for additional Documentum licensing, as well as providing security for the authoring system.  Because it is cross-platform capable, Migration Workbench was used to automatically publish content from the authoring system to the broader use publishing system.</p>
<p>This case is similar to the case of continually archiving documents, but instead of permanently moving objects over and removing them from the authoring system, individual versions are moved to the publishing system based on status without deleting them from them the source.  For example, suppose a content author&rsquo;s workflow has three states: Draft, Published, and Retired.  Initially a document has version 1.0 in Published state and 2.0 in Draft state. Rules in Migration Workbench could be written to select only documents in the Published state.  On the initial run, Migration Workbench would pick up version 1.0 and push it from the authoring system to the publishing system.  Later, when a user publishes version 2.0, which changes version 1.0 to the Retired state, Migration Workbench will pick-up that incremental change, delete version 1.0 from the publishing system, and push over version 2.0 in its place.</p>
<div align="center">
        <img src="/article-assets/images/mwb-additional-uses/publishing.jpg" border="0" alt="Fig. 2: Graphic of Publishing Documents">
<p class="figure">
            <b><br />
              Figure 2:<br />
            </b> Using Migration Workbench in a Publishing Role</p>
</p></div>
<h4>Content Receipt and Tracking</h4>
<p>Many organizations want to provide a way for their partners and vendors to contribute to business processes without giving them direct access to critical internal content management systems.  For example, a firm may need a way to receive receipts processed by an external payments management firm, or import lab data collected by a contract laboratory.  Migration Workbench can be used to receive this content, validate the metadata, and provide a confirmation that the content was properly processed.</p>
<p>The first step in providing a solution like this is to set up a content &lsquo;drop zone&rsquo;, such as an ftp site or a document upload web page.  Partners can use this to drop off content files and provide the associated metadata for that content in the form of XML or CSV files.  Using an upload web page allows for the creation of a database-backed web form, further simplifying the partner&rsquo;s upload process.</p>
<p>Migration Workbench is then run on a periodic basis to monitor that drop zone for new or changed content.  Validation rules are used to check that mandatory data fields are populated and all data is within expected ranges.  Migration Workbench keeps a record of what content was imported correctly as well as what content failed the validation rules and was placed in a holding state.  Standard reports can be used to easily identify content validation issues so the partner can take corrective action.  The next time Migration Workbench executes, incremental processing will identify the changes and re-process the content.  Once the content is successfully received and imported to the CMS, a dynamic cutover strategy can be configured in Migration Workbench to delete the content from the drop zone and send the partner a receipt confirmation.</p>
<div align="center">
        <img src="/article-assets/images/mwb-additional-uses/content_receipt.jpg" border="0" alt="Fig. 3: Graphic of External Document Receipt">
<p class="figure">
            <b><br />
              Figure 3:<br />
            </b> Using Migration Workbench to Import Documents from External Vendors</p>
</p></div>
<h4>Receiving Documents from Scanning Systems</h4>
<p>Many large organizations wrestle with processing extremely large volumes of documents created by scanning systems.  Common examples of these solutions include scanning of insurance claims, invoices, and trade confirmations.  The scanning system typically generates an image file of the document and places that file into a file share.  The scanning system&rsquo;s OCR software then parses metadata values from the body of the document and creates a metadata record in a database, XML, CSV, or similar data file.</p>
<p>Similar to the case of content receipt and tracking, Migration Workbench can be configured to recurse through the file share where the scanned images are located, identify new or changed content, and look up the metadata that corresponds to that piece of content.  Transformation rules easily map that content and its metadata to the CMS&rsquo;s schema, and dynamic cutover rules can be put in place to remove these from the file share once they are imported into the CMS.</p>
<h4>Loading Test Systems with Production Data</h4>
<p>Many well intended system releases and updates are immediately plagued by defects and issues for the simple reason that they were tested with data that was not representative of real world production data.  Content management applications, in particular, are likely to encounter data inconsistencies and errors that simply cannot be anticipated with artificially fabricated test content and data.</p>
<p>With Migration Workbench, application developers have the ability to easily migrate select subsets of content and metadata from live production systems back to their test systems without impacting production system availability.  As testing progresses, inclusion and exclusion rules can be written and adjusted to change the type and quantity of production documents being used in the test system.  Migration Workbench&rsquo;s incremental functionality also allows for the test data to easily be kept up to date with content in the production system, if needed.</p>
<div align="center">
        <img src="/article-assets/images/mwb-additional-uses/test_data_load.jpg" border="0" alt="Fig. 4: Graphic of Loading Test Data">
<p class="figure">
            <b><br />
              Figure 4:<br />
            </b> Using Migration Workbench to Populate Test Data</p>
</p></div>
<h4>Assembling Document Bundles for Submittal</h4>
<p>For companies in regulated industries such as pharmaceuticals, there can often be thousands of documents associated with a single submittal to a regulatory agency.  Using Migration Workbench&rsquo;s rules-based document selection capabilities, it is easy to configure individual export batches to collect all documents and metadata associated with a single regulatory submission.  This could also include the selection of appropriate versions and renditions for assembly.</p>
<p>Another similar use case is the publishing of engineering drawings.  Engineering organizations often create thousands of engineering drawings as work product, and face significant liability if the wrong versions were to be issued to their clients.  There is a substantial need to be able to accurately bundle the correct documents in various configurations (site drawings, structural, electrical, plumbing, etc.) and ensure the correct versions are consistently used.</p>
<p>The rules-based approach used by Migration Workbench gives you the power and flexibility to precisely define the documents and data to be packaged.  Additionally, incremental processing means that you can easily respond to follow-up requests for documents that have changed since the last submittal.  Re-running the export will update the submittal with the just documents that have changed or are new.</p>
<h4>Metadata Quality Analysis and Reporting</h4>
<p>&#8220;How clean is my data?&#8221; or &#8220;What errors will I get if I run this migration batch?&#8221; are common questions faced by CMS administrators.  Migration Workbench can be used to make this analysis easier.</p>
<p>Data validation rules can be put in place early in the migration process, even before transformation and mapping rules are defined.  Migration Workbench can be configured to run in a &#8216;test mode&#8217;, where all of the rules are evaluated and reported on, but no content or metadata is actually imported into the target system.  This gives the user a preview of what exceptions and issues to expect without incurring the time expense of actually importing content.</p>
<h3>
        <a name="head3" class="section">Conclusion</a><br />
    </h3>
<p>From the examples above, it is easy to see that Migration Workbench can be used to solve a variety of content management problems above and beyond just migrations.  Capabilities such as true incremental re-processing of changes, dynamic cutover, rules-based transformations, and live-to-live migrations provide users with the flexibility to create innovative solutions for a broad range of CMS challenges.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2009/mwb-additional-uses/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Web Publisher Technical Architecture: A Primer</title>
		<link>http://www.bluefishgroup.com/2009/web-publisher-technical-architecture-a-primer/</link>
		<comments>http://www.bluefishgroup.com/2009/web-publisher-technical-architecture-a-primer/#comments</comments>
		<pubDate>Sat, 28 Feb 2009 12:00:00 +0000</pubDate>
		<dc:creator>Nicki DuBose</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Web Content Management]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=398</guid>
		<description><![CDATA[Overview When you think of a web content management solution, you might envision a toolset that simplifies web content creation and maintenance for non-technical content authors. EMC Documentum fulfills this web content management vision through a suite of products. A basic Documentum web publishing environment configuration will utilize three Documentum products: Web Publisher, to simplify [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Overview</a><br />
    </h3>
</p>
<p>When you think of a web content management solution, you might envision a toolset that simplifies web content creation and maintenance for non-technical content authors.  EMC Documentum fulfills this web content management vision through a suite of products.  A basic Documentum web publishing environment configuration will utilize three Documentum products: Web Publisher, to simplify web content creation and modification, Content Server, to enable content management, and Site Caching Services (SCS), to publish content from a content repository to a website.</p>
<p>If you&#8217;re new to Web Publisher, you might want to start by checking out Marc Perlman&#8217;s <a href="">Demo: The Power of Web Publisher</a> to get a feel for how content is created in Web Publisher.  Otherwise, a good way to gain an understanding of Documentum web publishing is to follow a piece of content through the system from creation to publication on a website.</p>
<ol>
<li>A content manager starts the process by accessing Web Publisher through a web browser.</li>
<li>Within the Web Publisher application, the content manager creates a piece of web content by filling out a form using Web Publisher&#8217;s template based authoring tools.  The content manager sets any number of attributes, such as title and content author, on the new piece of content.</li>
<li>The new piece of content is created in the WIP (work in progress) lifecycle state and stored in the file store of the Documentum repository.  Under the covers the content is stored as an XML file and the attributes that describe the content are stored in the relational database (RDBMS) within the repository.  When the content manager selects the &#8220;webview&#8221; option in Web Publisher, the page template is transformed into a format that can be published to a website, such as JSP, ASP, or HTML.</li>
<li>Next, Site Caching Services (SCS) performs a publish operation, which copies the transformed web page to the target website machine.  Assuming the environment is configured to publish attribute values then the SCS database will also be updated with the content object attributes.</li>
<li>The content and its attributes now reside on the WIP website where they can be reviewed for any typos or other errors.</li>
<li>After the content manager is satisfied with the content, he or she launches the content on an approval workflow.  The content is automatically promoted to the Staging lifecycle state and is forwarded to an editor for review.  The editor approves the content which is then promoted to the Active lifecycle state.  Both the content and its corresponding attributes are then published to the production web server(s).</li>
</ol>
<div align="center">
        <img src="/article-assets/images/wp-arch-primer/basic-config.png" border="0" alt="Fig. 1: Documentum WCM Environment Configuration">
<p class="figure">
            <b><br />
              Figure 1:<br />
            </b> Documentum WCM Environment Configuration</p>
</p></div>
<h3>
        <a name="head2" class="section">Documentum Web Publishing Environment Components</a><br />
    </h3>
<p>A typical Documentum web publishing environment requires three Documentum products: Web Publisher, Content Server, and Site Caching Services.  In addition to these three products from Documentum, a custom website is required to complete a WCM environment.  Below I&#8217;ve detailed some of the key elements within each of the required components.</p>
<h4>Web Publisher</h4>
<p>Web Publisher is a web application built on the EMC Documentum Web Development Kit (WDK) framework.  The WDK toolkit is a Java based library of reusable components and controls that enable content management functions for Documentum through a web application.  Web Publisher is an extension to the WDK framework that simplifies the creation and maintenance of web content using form based content editing.  Web Publisher is installed in three parts: the web application, the DocApp, and the server files.  The Web Publisher web application and WDK are installed in an application server such as Apache Tomcat, BEA WebLogic, or IBM WebSphere.  For a complete list of supported application servers and versions, refer to the Web Publisher Release Notes for your version.</p>
<p>    <strong>Web Publisher Contributor</strong></p>
<p>Web Publisher Contributor is not a separate product or installation from Web Publisher.  Contributor is another user interface option for the user to select at login time.  Web Publisher Contributor is aimed at the casual content author.  Contributor provides a simplified interface for the casual contributor by focusing on the tasks that they perform on a regular basis.  For more information on the Contributor interface, read <a href="">&#8220;Introduction to Web Publisher Contributor&#8221;</a>.</p>
<p>    <strong>Documentum Administrator</strong></p>
<p>Documentum Administrator (DA) is a web application that provides access to administrative functions within Documentum.  DA gives system administrators access to monitor, configure and maintain Documentum servers, repositories, and federations.  As part of the Web Publisher installation, DA will also be updated with additional jobs for configuring and monitoring Web Publisher and site publishing functionality.  DA access is required to complete the configuration of a Documentum web publishing environment.</p>
<h4>Content Server</h4>
<p>Documentum Content Server is the component responsible for managing the content.  Content Server enables functions such as document versioning, workflow, and content security for content stored within a given repository.  The Content Server handles all access to the content repository.  Content Server is a required component in any Web Publisher solution.</p>
<p>    <strong>Repository</strong></p>
<p>A content repository (or docbase) stores the tables, indexes and content files used by Documentum Content Server.  The repository is essentially a relational database to store content attribute values (or metadata) and a file store to house the content files.  </p>
<p>In addition to the Web Publisher web application components and controls mentioned above, Web Publisher also requires a DocApp and a set of Web Publisher server files installed on the Content Server.</p>
<p>    <strong>Web Publisher DocApp</strong></p>
<p>The Web Publisher DocApp provides the additional workflows and lifecycle scripts for web content management, as well as a number of objects used to manage permissions, groups, and roles. The DocApp must be installed into any repository that will utilize the Web Publisher application.   The DocApp is installed using Application Installer or DAR Installer, depending on the Web Publisher version.</p>
<p>    <strong>Web Publisher Server Files</strong></p>
<p>The Web Publisher server files are made up of two jars files that contain Java methods for changing permissions and executing the additional jobs and methods required for web content management.  These files are installed on the Content Server to run in the separate Java Method Server application installed with Documentum Content Server.</p>
<p>    <strong>Java Method Server</strong></p>
<p>The Java Method Server is an application included by default with the Content Server installation.  The Method Server is installed into an application server; either Apache Tomcat for DCTM version 5, BEA WebLogic for DCTM version 6, or JBOSS for DCTM version 6.5.  The method server is a web application that allows custom code to execute on the server, independent of the client.  The Method Server is often used to execute long-running processes or to execute processes that require super user privileges.</p>
<h4>Site Caching Services</h4>
<p>Site Caching Services is used to publish content from a Documentum repository to a website.  SCS can also be configured to publish document attribute values (or metadata) to an external database for consumption by a website application.  The published attribute values can be useful when creating dynamic web pages.  For instance, the SCS (or webcache) database might be queried for all news items published with a press date in the last 30 days to create a dynamic news listing page.  Additionally, SCS can be configured to write relation objects to an external database.  The published relation object information can be useful when building a web page composed of related page snippets.</p>
<p>SCS is installed in two parts on different machines; the &#8220;source&#8221; is installed on the content server and the &#8220;target&#8221; on the web server host machine.  SCS uses the source and target for communication between the content server and the web server machine(s).  SCS can manage multiple websites for a single repository.  For instance, a typical Web Publisher environment will support 3 distinct websites: WIP (Work In Progress), Staging, and Active.  SCS can be configured to publish all content in the WIP lifecycle state to the WIP website, content in the Staging state to the Staging site, and so forth.</p>
<h4>Published Website</h4>
<p>Web Publisher is NOT a website presentation engine.  In other words, you must create a custom web application framework to support dynamic web pages on your website.  Unless the website being maintained and published from Web Publisher is a simple, static HTML site then a presentation engine is required to render the website.  Using one of these presentation engines or web application frameworks requires custom development to handle things like database access, website security, and dynamic page rendering.  To leverage all of the best features of Web Publisher, a presentation engine should also support querying the published SCS database for content attribute values and related objects.  Here at Blue Fish, we&#8217;ve developed and refined a website component library to enable website security, display navigation enabled by Navigation Manager, and render many of the most common dynamic pages.</p>
<h3>
        <a name="head3" class="section">Optional Products and Add-Ons</a><br />
    </h3>
<p>There are a number of optional add-ons offered by EMC Documentum for simplifying content authoring, creating and deploying portlets, and managing replication of content to multiple web servers, among other things.</p>
<h4>Page Builder</h4>
<p>Web Publisher Page Builder is a browser based editor that enables web page development while viewing the web page as it will appear on the actual website.  Page Builder also provides a tool for building additional content templates.  The key benefit of Page Builder is that it allows the user to manage layout in addition to content.  The content author will edit a page as it will appear on the end website, unlike the form based editing in the base Web Publisher product.  Page Builder is simply another DocApp installed in a Web Publisher repository.   Look out for an upcoming article about Page Builder in the near future.</p>
<h4>Portlet Builder</h4>
<p>Documentum Portlet Builder is an optional product add-on that is used to create and deploy portlets to a portal server.  Portlet Builder provides additional templates and wizards for creating portlets, as well as a portal server target for identifying the portal servers to which portlets can be published.  Like Page Builder, Portlet Builder is also a DAR (or DocApp) installed in a Web Publisher repository.  A separate portal server is required to make use of the portlets published from Web Publisher. </p>
<h4>Site Deployment Services</h4>
<p>Site Deployment Services (SDS) is a Documentum product that facilitates the replication of content to multiple websites and databases.  SDS is often used to keep multiple web servers in sync and refreshed with the latest content published from SCS.  Site Caching Services can be configured to work with SDS, such that a publish operation from SCS to target server A will trigger the replication of content to targets B and C.  Using the same example, if the replication of content from Target A to B is successful, but replication to Target C fails, then the entire transaction can be rolled back.  This ensures a consistent website experience no matter which target site a visitor sees.</p>
<p>SDS is not dependent on the repository in any way.  SDS is made up of a series of Tuners installed on each of the host machines.  SDS uses Tuners to subscribe to various Channels through which content is replicated.  Whenever a channel has changed (i.e. content has been added or removed), the Transmitter is responsible for distributing content and updates to each of the other Tuners subscribed to the updated Channel.  The diagram below provides a simplified view of the communications between the various components.  To learn more about installing and configuring SDS read <a href="">&#8220;Site Deployment Services Rapid Install, Config and Troubleshooting&#8221;</a>.</p>
<div align="center">
        <img src="/article-assets/images/wp-arch-primer/sds.png" border="0" alt="Fig. 2: Simplified illustration of SDS content replication">
<p class="figure">
            <b><br />
              Figure 2:<br />
            </b> Simplified illustration of SDS content replication</p>
</p></div>
<h3>
        <a name="head4" class="section">Conclusion</a><br />
    </h3>
<p>The EMC Documentum product suite is capable of delivering a robust and comprehensive web publishing environment, but understanding all of the components is key to configuring a strong solution to meet the needs of your business.  I hope this article has provided a basic understanding of those components required by any Documentum web publishing environment and an idea of when to use some of the optional components and add-ons.</p>
<h3>
        <a name="head5" class="section">References</a><br />
    </h3>
<ul>
<li>Web Publisher Administration Guide</li>
<li>Web Publisher User Guide</li>
<li>Site Caching Services User Guide</li>
<li>Site Deployemnt Services Administrator&#8217;s Guide</li>
</ul>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2009/web-publisher-technical-architecture-a-primer/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>New Article: Tips For Making Your Website Section 508 Compliant</title>
		<link>http://www.bluefishgroup.com/2008/new-article-tips-for-making-your-website-section-508-compliant/</link>
		<comments>http://www.bluefishgroup.com/2008/new-article-tips-for-making-your-website-section-508-compliant/#comments</comments>
		<pubDate>Wed, 24 Dec 2008 17:07:49 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=396</guid>
		<description><![CDATA[Marc Perlman, a consultant here at Blue Fish that specializes in web content management solutions, has just written an article full of tips on how to make your web site accessible for visitors with a visual disability. Read Tips For Making Your Website Section 508 Compliant.]]></description>
				<content:encoded><![CDATA[<p>Marc Perlman, a consultant here at Blue Fish that specializes in web content management solutions, has just written an article full of tips on how to make your web site accessible for visitors with a visual disability.</p>
<p>Read <a href="http://www.bluefishgroup.com/library/2008/tips-for-making-your-website-section-508-compliant/">Tips For Making Your Website Section 508 Compliant</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/new-article-tips-for-making-your-website-section-508-compliant/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New Article: Introduction to the WDK Combo Container</title>
		<link>http://www.bluefishgroup.com/2008/new-article-introduction-to-the-wdk-combo-container/</link>
		<comments>http://www.bluefishgroup.com/2008/new-article-introduction-to-the-wdk-combo-container/#comments</comments>
		<pubDate>Wed, 24 Dec 2008 17:07:41 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=397</guid>
		<description><![CDATA[Jason Duke is one of the developers who helped Documentum add drag-and-drop capabilities to WebTop back in version 5.3. Since then, he&#8217;s worked on several WDK development projects for some of our largest clients. Jason has just published an article about the WDK Combo Container, one of the trickiest components to customize in the entire [...]]]></description>
				<content:encoded><![CDATA[<p>Jason Duke is one of the developers who helped Documentum add drag-and-drop capabilities to WebTop back in version 5.3. Since then, he&#8217;s worked on several WDK development projects for some of our largest clients. Jason has just published an article about the WDK Combo Container, one of the trickiest components to customize in the entire WDK library (for the uninitiated, the Combo Container is the control that enables users to select multiple documents at once and then perform an action on them). </p>
<p>Jason&#8217;s article is called <a href="http://www.bluefishgroup.com/library/2008/introduction-to-wdk-combo-container/">Introduction to the WDK Combo Container</a>, and it&#8217;s worth a read if you&#8217;re going to be doing any serious WDK development.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/new-article-introduction-to-the-wdk-combo-container/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tips For Making Your Website Section 508 Compliant</title>
		<link>http://www.bluefishgroup.com/2008/tips-for-making-your-website-section-508-compliant/</link>
		<comments>http://www.bluefishgroup.com/2008/tips-for-making-your-website-section-508-compliant/#comments</comments>
		<pubDate>Mon, 22 Dec 2008 12:00:00 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Web Content Management]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=394</guid>
		<description><![CDATA[Introduction Over the years Blue Fish has been asked to build Web Content Management solutions for a wide range of clients. With any WCM solution, our goal is to enable non-technical users to create and maintain a highly usable website. Section 508 of the Rehabilitation Act of 1973 specifically mandates that government and government funded [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Introduction</a><br />
    </h3>
<p>Over the years Blue Fish has been asked to build Web Content Management solutions for a wide range of clients. With any WCM solution, our goal is to enable non-technical users to create and maintain a highly usable website. Section 508 of the Rehabilitation Act of 1973 specifically mandates that government and government funded websites be accessible for handicapped individuals, but many of our clients are simply interested making their site usable by peoples with vision disabilities.</p>
<p>Many of the good design decisions and development habits that we follow can help make your website accessible to the visually impaired &#8211; even if the law does not mandate your website to be Section 508 compliant. In general, these practices result in solutions that are more useable for persons with and without disabilities. So even though your website might not be required by federal law to meet the standards laid out in Section 508, you might just find that implementing some of the ideas that follow will result in a better website.</p>
<p>To be clear, I&#8217;m not describing a definitive &#8220;How To&#8221; with this article. Nor are we trying to explain a solution for every single facet of Section 508 of the Rehabilitation Act of 1973. There are <a href="#head8">plenty of resources</a> available on the web that details the minutiae of Section 508. By leveraging some of these tips on your Web Publisher based WCM solution, I hope you&#8217;ll enhance the accessibility and usability of your website for all users regardless of health and disabilities.</p>
<h3>
        <a name="head2" class="section">A Little Section 508 Primer</a><br />
    </h3>
<p>Most companies and organizations that wish to make their website accessible for the visually impaired or disabled follow the technical standards defined by Section 508 of the Rehabilitation Act of 1973. Section 508 codifies those technical requirements and all Federal agencies (as well as private institutions that receive funding from or under contract with a government agency) must meet during the development, procurement, use and maintenance of information technology solutions.  The standards defined in Section 508 are intended to give disabled users &#8211; whether they are government employees or the public &#8211; comparable access to the information available to all other users which is why so many websites are designed to meet the standards regardless of legal obligation.</p>
<p>With regards to websites and other web based solutions, Section 508 provides sixteen provisions that must be met for a solution to be accessible to disabled peoples. These sixteen provisions are laid out in Sub-part B, 1194.22 of Section 508 and are <a target="_blank" href="http://www.section508.gov/index.cfm?FuseAction=content&#038;ID=12#Web">widely detailed on various web resources</a>, so listing them in this article would be redundant at best. The ultimate goal of the sixteen provisions &#8211; and the following best practices &#8211; is to ensure accessibility for visually impaired persons using assistive technologies such as screen readers by providing contextual text labels and descriptions for graphics, navigation, and other web page elements.</p>
<p>Although originally added in 1986 as an amendment to the Rehabilitation Act of 1973, it was not until 1998 that the current implementation and enforcement of Section 508 came to fruition. It is a common misunderstanding to think Section 508 is part of the Americans with Disabilities Act of 1990; Section 504 of the Rehabilitation Act of 1973 was the basis for the ADA, but that is the only connection.  Similarly, the World Wide Web Consortium&#8217;s Web Content Accessibility Guidelines (WCAG) are related to &#8211; but not part of &#8211; Section 508 compliance. The WCAG are voluntary and unenforceable whereas Section 508 provides a course of action against violators of the law. In the case of the WCAG, there is indeed significant overlap between the guidelines and the sixteen provisions outlined by Section 508. In some instances, adhering to just one set of rules could quite possibly result in complete compliance with the other set, but the only way to ensure 100% compliance with Section 508 of the Rehabilitation Act of 1973 is to explicitly check against all sixteen points.</p>
<h3>
        <a name="head3" class="section">Design For Usability, Achieve Accessibility</a><br />
    </h3>
<p>Section 508 of the Rehabilitation Act of 1973 is in place to guarantee that disabled users of a given website can access the same information as all other users. There&#8217;s no guarantee that disabled users (or anyone else, for that matter) will be able to actually <i>use</i> the website efficiently and effectively.</p>
<p>When I first started designing and building WCM solutions, I used to spend a lot of time at the end of projects checking that the resulting website was accessible. Over time, I realized that if the website was designed for usability, the accessibility often came for free.  A few simple tips to remember when designing for usability will also help accessibility include:</p>
<ul>
<li>
<p>
                <b>Don&#8217;t rely on color as a differentiating factor</b> -</p>
<p>At this point, many of us are familiar with color coded alerts and stoplights. It&#8217;s intuitive to many that red means &#8220;danger&#8221; or &#8220;stop&#8221; and green means &#8220;safe&#8221; or &#8220;go&#8221;. Unfortunately, for a disabled user of your website &#8211; for example, someone with color 		blindness &#8211; differentiating red, yellow, and green icons might not be possible.</p>
<p>For example, in Figure 1, the availability of Apple&#8217;s iPhone is indicated on a per store basis solely by the color of the stop light.</p>
<div align="center">
                <img src="/article-assets/images/section_508_compliance_01.jpg" border="0" alt="Fig. 1: Using Color As The Sole Indicator">
<p class="figure">
                    <b><br />
              Figure 1:<br />
            </b> Using Color As The Sole Indicator</p>
</p></div>
<p>While the availability indicated in this image <i>may</i> have been intuitive to you and me, it&#8217;s not even necessarily readable to an individual with color blindness. Rather than just relying on green vs. red, Figure 2 shows a more accessible and useable 		representation of the same information from <a target="_blank" href="http://www.topmuffin.com/3g-iphone-availability">another website</a>.</p>
<div align="center">
                <img src="/article-assets/images/section_508_compliance_02.jpg" border="0" alt="Fig. 2: Using Color and Other Indicators">
<p class="figure">
                    <b><br />
              Figure 2:<br />
            </b> Using Color and Other Indicators</p>
</p></div>
<p>Figure 2 is a much better usability and accessibility decision; There is no mistaking that there are two states &#8211; in stock vs. out of stock &#8211; because the icons are not only two different colors, they are two different shapes.</p>
</li>
<li>
<p>
                <b>Use contextual and descriptive text for links and buttons</b> &#8211; </p>
<p>How many times have you read through a long block of text on a website and, at the bottom, been presented with a link that merely says &#8220;Read More&#8221;? If you&#8217;ve been reading a lot about ACME corporation, the real question is &#8220;Read More What.&#8221; By 	changing 	that 	link text to say &#8220;Read More About ACME&#8217;s Solution&#8221;, you&#8217;ve already made the page significantly more user friendly.</p>
<p>By using descriptive text for links and buttons, as described in the simple example above, your website moves closer to being Section 508 compliant. A disabled user who is visiting the website with a text reader isn&#8217;t going to have the visual clue that 	the 	&#8220;Read 	More&#8221; link is directly below a huge block of text about ACME&#8217;s Solution. What happens if there are multiple &#8220;Read More&#8221; links on the same page? Changing the links to say &#8220;Read More About ACME&#8217;s Solution&#8221; and &#8220;Read More About Working For ACME 		Corporation&#8221; is inherently more usable and accessible for all users.</p>
<div class="callout">
<p>
                    <b>Bonus</b>
                </p>
<p>Not only does using contextual and descriptive text for links and buttons make your site more usable, it will likely help with your search engine ranking.</p>
</p></div>
</li>
<li>
<p>
                <b>Use text, not images, in page titles and navigational elements</b> &#8211; </p>
<p>Once upon a time, in order to provide compelling page titles and navigational cues to the user, these elements were often stored as images, with different images being presented on mouse roll-over, or when the node was active.  With the advent of 	CSS, 		background images, and other more advanced styling techniques for web pages, using images for page titles and navigational elements is now all but obsolete, and when employed it presents usability and accessibility issues. Not only will a text reader not 	be able 	to 	read and interpret the images for disabled users, maintaining and updating these images becomes a potential nightmare for your website administrators.</p>
<p>A robust content management system will allow business users to create and maintain the navigational hierarchy without IT department support. Figure 3 shows an example of a page title, bread crumbing, and menus that don&#8217;t use images. </p>
<div align="center">
                <img src="/article-assets/images/section_508_compliance_03.jpg" border="0" alt="Fig. 3: Text Based Page Elements">
<p class="figure">
                    <b><br />
              Figure 3:<br />
            </b> Text Based Page Elements</p>
</p></div>
<p>Instead of using images for these page elements, simply rendering text over backgrounds looks just as great as using images and makes updates relatively painless for content authors. In this example, the business user is able to perform changes 	without 		having to call up the resident Photoshop expert to get a new image ready to go.</p>
</li>
</ul>
<h3>
        <a name="head4" class="section">Use Templated Authoring To Your Advantage</a><br />
    </h3>
<p>When you use a content management system with templated authoring &#8211; such as EMC Documentum&#8217;s Web Publisher &#8211; to administer your WCM solution, you inherently gain the power to change one template and apply those changes to all the relevant instances of content. While designing our clients&#8217; Web Publisher based solutions, a few common patterns repeatedly appear in the website markup that can be easily applied to all pages thanks to templated authoring. These little tweaks to your markup will not only result in a more usable site for all visitors, but will help your solution achieve Section 508 compliance.</p>
<ul>
<li>
<p>
                <b>Include a link to skip the navigation</b> &#8211; </p>
<p>Imagine your favorite e-commerce site with 10 tabs across the top of the website and an additional 5 or more submenu options that appear every time you mouse over one of those tabs. Each one of those 10 tabs and 5 dropdown options is HTML that 	will be read by the text reader on every single page load; If you&#8217;re not visually impaired, it&#8217;s hard to fathom listening to a site reader read back 50 or more navigational elements <i>before</i> you even find out that the product page you&#8217;re viewing isn&#8217;t the right product. </p>
<p>While it&#8217;s easy enough for most sighted users to focus immediately on the body of the page and skip the global navigation, the same is not true of disabled persons using a site reader. By including a link to the meat of the page at the very top of every 	page, a visually impaired user can quickly jump over the navigation.</p>
<p>It&#8217;s just common courtesy and good practice to give every visitor to your website a quick path to the heart of every page.</p>
</li>
<li>
<p>
                <b>Include descriptions for all site assets</b> &#8211; </p>
<p>One of the most important provisions of Section 508 of the Rehabilitation Act of 1973 is that all images must have alternate text descriptions. While it may be obvious that regular content images need these descriptions, it&#8217;s easy to overlook all those site assets &#8211; like spacer images and logos &#8211; but they too must have descriptions. During construction of your presentation files, set the <code>alt</code> attribute for the <code>img</code> tag appropriately. For blank images used as spacers, an <code>alt=""</code> is perfectly acceptable for Section 508 compliance.</p>
</li>
<li>
<p>
                <b>Design for device independence</b> &#8211; </p>
<p>It&#8217;s easy to forget that not every user is visiting your website with a mouse. Quickly check all your markup files for device specific references (such as <code>onMouseOver</code>) and change them to device independent instances (such as <code>onFocus</code>).</p>
</li>
<li>
<p>
                <b>Design for CSS and JavaScript independence</b> &#8211; </p>
<p>Cascading Style Sheets (CSS) and JavaScript are a wonderful way to make your website look great. Unfortunately, looking great doesn&#8217;t help visually impaired visitors using a text reader or users on browsers with limited functionality (Wireless devices, console gaming systems, etc). </p>
<p>It is important to design your presentation files to render content in a readable usable manner without CSS and JavaScript. By creating your solution so the markup and content renders in a readable format before the application of CSS and JavaScript, you can ensure accessibility for all users. </p>
</li>
</ul>
<h3>
        <a name="head5" class="section">Use Web Publisher to Ensure Compliance For Images and Tables</a><br />
    </h3>
<p>In addition to the aforementioned design decisions than can be easily incorporated into your XSL presentation files, there are a few tips and tricks that can help ensure your Web Publisher based WCM solution is Section 508 compliant. </p>
<h4>Ensuring Section 508 compliance for author selected images</h4>
<p>As mentioned earlier, a prime directive of Section 508 is to ensure all images include descriptive alternative text for the visually impaired. While it&#8217;s straight forward enough to hard code <code>alt</code> attributes in the XSL presentation files for site assets, what about images added or selected by content authors via the Web Publisher content editor? </p>
<p>There are two ways that content authors can add images to an instance of content in Web Publisher:</p>
<ol>
<li>Via the Graphic widget</li>
<li>Via the Rich Content Area widget</li>
</ol>
<p>When a content author selects an image using the Graphic Widget (Figure 4), Web Publisher does not allow the author to enter any descriptive text to be use as the <code>alt</code> attribute for the published rendition. </p>
<div align="center">
        <img src="/article-assets/images/section_508_compliance_04.jpg" border="0" alt="Fig. 4: Selecting an image with a graphic widget">
<p class="figure">
            <b><br />
              Figure 4:<br />
            </b> Image selection widget</p>
</p></div>
<p>A simple straight forward solution is to include another field in your template that allows a content author to enter a description (Figure 5). </p>
<div align="center">
        <img src="/article-assets/images/section_508_compliance_05.jpg" border="0" alt="Fig. 5: Entering an alternate description">
<p class="figure">
            <b><br />
              Figure 5:<br />
            </b> Alternate text description entry</p>
</p></div>
<p>Now your XSL presentation file can render the <code>img</code> tag with both the <code>src</code> attribute from the graphic widget and an <code>alt</code> attribute using the descriptive text. If this description field is optional, Section 508 compliance can still be ensured by generating an <code>alt</code> attribute text from the image name in the XSL processing, but this will only ensure compliance with the letter of the law, not the spirit. To make your site truly accessible, every image should have a descriptive <code>alt</code> attribute.</p>
<p>If a content author adds an image via the Rich Content Area widget, the author can add the <code>alt</code> text description by either right clicking on the image and selecting &#8220;Image Properties&#8221; or double-clicking on the image. At that point, the content author can enter the descriptive text in the &#8220;Alternative Text&#8221; field of the &#8220;Image Properties&#8221; window shown in Figure 6.</p>
<div align="center">
        <img src="/article-assets/images/section_508_compliance_06.jpg" border="0" alt="Fig. 6: Image Properties for a Rich Content Area image">
<p class="figure">
            <b><br />
              Figure 6:<br />
            </b> Image Properties for a Rich Content Area image</p>
</p></div>
<h4>Ensuring Section 508 compliance for tables</h4>
<p>Another major provision of Section 508 is to ensure accessibility of data contained in tables. Similar to images, tables are required to have descriptive identifiers to be Section 508 compliant. </p>
<p>Section 508 has two requirements related to tables:</p>
<ol>
<li>&#8220;Row and column headers shall be identified for data tables.&#8221;</li>
<li>&#8220;Markup shall be used to associate data cells and header cells for data tables that have two or more logical levels of row or column headers.&#8221;</li>
</ol>
<p>Since visually impaired visitors are unable to ascertain the contextual clues (such as color highlighting) that might indicate a table has a header row, these two requirements ensure accessibility. In general, tables should be properly formatted and used for data representation, not for general page layout. </p>
<p>Like images added via the Rich Content Area widget, Web Publisher enables content authors to easily identify and mark tables as necessary to be Section 508 compliant.  By highlighting the table cells, right clicking, and selecting &#8220;Cell Properties&#8221;, a content author can quickly add the appropriate tags to make a table Section 508 compliant. The &#8220;Cell Properties&#8221; window (Figure 7) allows an author to mark rows and/or columns as header cells (important for requirement #1) as well as set the Header ID and the Headers attribute (both important for requirement #2).</p>
<div align="center">
        <img src="/article-assets/images/section_508_compliance_07.jpg" border="0" alt="Fig. 7: Cell Properties for a Rich Content Area table">
<p class="figure">
            <b><br />
              Figure 7:<br />
            </b> Cell Properties for a Rich Content Area table</p>
</p></div>
<p>By checking the &#8220;Header cell&#8221; box, the previously selected cells are changed from td elements to th elements. Assistive devices will read this markup and inform a user that these cells are header cells and not data cells.</p>
<p>To link a data cell with a header cell, as required by #2, a content author can set the &#8220;Header ID&#8221; on the header cell(s) and then set the &#8220;headers&#8221; on the data cell. </p>
<p>As with rich content area images, there is no way to be certain content authors have properly entered these descriptors for a table. Blue Fish uses processing in the XSL presentation file as well as best practice education during training to help our clients ensure compliance.</p>
<h3>
        <a name="head6" class="section">Documentum Accessibility Report</a><br />
    </h3>
<p>Beginning with D6, Documentum has included a new option &#8211; the Accessibility Report &#8212; for the Rich Content Area widget in Web Publisher. This option, when enabled, allows content authors to generate a variety of simple reports for a rich content area that highlight potential compliance issues.</p>
<p>To run the Accessibility Report, a content author clicks on the accessibility report icon in the rich content area toolbar (Figure 8 ) and is presented with the report window (Figure 9).</p>
<div align="center">
        <img src="/article-assets/images/section_508_compliance_08.jpg" border="0" alt="Fig. 8: Rich Content Area toolbar">
<p class="figure">
            <b><br />
              Figure 8:<br />
            </b> Rich Content Area toolbar</p>
</p></div>
<div align="center">
        <img src="/article-assets/images/section_508_compliance_09.jpg" border="0" alt="Fig. 9: D6 Accessibility Report">
<p class="figure">
            <b><br />
              Figure 9:<br />
            </b> D6 Accessibility Report</p>
</p></div>
<p>The accessibility report window allows content authors to check against both Section 508 as well as the WCAG standards. Additionally, by checking the &#8220;Errors&#8221;, &#8220;Warning&#8221;, and &#8220;Manual Checks&#8221; boxes, the content author is given different information to consider for the content&#8217;s compliance. This new tool combined with the best practices already outlined can help ensure Section 508 compliance for Web Publisher based WCM solutions.</p>
<div class="callout">
<p>
            <b>Note</b>
        </p>
<p>While documented as an option for the Rich Content Area widget in D6 and D6 SP1, how to enable the Accessibility Report toolbar option was not documented at the time of publication. To enable this option, the following steps must be taken.</p>
<p>In the <i>/wp/wp/editors/contenteditor/resources/editliveConfig.xml</i> file located on the Application Server:</p>
<ol>
<li>
<p>Insert</p>
<p>
                        <code>&lt;toolbarButton name="Accessibility"/&gt;</code>
                    </p>
<p>immediately after</p>
<p>
                        <code>&lt;toolbarButton name="tlbSpelling"/&gt;</code>
                    </p>
</li>
<li>
<p>Insert</p>
<p>
                        <code>&lt;action-mapping&gt;<br />
        &lt;contentwidget-action&gt;accessibilitycheck&lt;/contentwidget-action&gt;<br />
        &lt;editlive-action&gt;tlbAccessibility&lt;/editlive-action&gt;<br />
        &lt;editlive-action&gt;Accessibility&lt;/editlive-action&gt;<br />
&lt;/action-mapping&gt;</code>
                    </p>
<p>immediately after</p>
<p>
                        <code>&lt;action-mapping&gt;<br />
        &lt;contentwidget-action&gt;spellcheck&lt;/contentwidget-action&gt;<br />
        &lt;editlive-action&gt;tlbSpelling&lt;/editlive-action&gt;<br />
        &lt;editlive-action&gt;BackgroundSpellChecking&lt;/editlive-action&gt;<br />
&lt;/action-mapping&gt;</code>
                    </p>
</li>
<li>
<p>Restart the Web Publisher Application Server</p>
</li>
<li>
<p>In each XML rules file where the Accessibility Report is desired, add the attribute-value pair of <code>Accessibility="Y"</code> to the appropriate <code>&lt;content&gt;</code> tag(s)</p>
</li>
</ol>
</p></div>
<h3>
        <a name="head7" class="section">Conclusion</a><br />
    </h3>
<p>Compliance with Section 508 of the Rehabilitation Act of 1973 is required for all government affiliated or funded websites to ensure accessibility for all visitors. With a little bit of foresight, adoption of some best practices, and good overall usability, compliance for your website will come almost naturally.  Regardless of whether or not your website is required by law to be Section 508 compliant, enacting many of these recommendations will help create a solution that is more useable for persons with or without a disability.</p>
<h3>
        <a name="head8" class="section">Further Reading</a><br />
    </h3>
<ul>
<li>
            <a target="_blank" href="http://www.section508.gov/">http://www.section508.gov/</a> &#8211; The Road to Accessibility includes a comprehensive resource that details Section 508 guidelines as well as a searchable database for compliant products.</li>
<li>
            <a target="_blank" href="http://en.wikipedia.org/wiki/Section_508_Amendment_to_the_Rehabilitation_Act_of_1973">http://en.wikipedia.org/wiki/Section_508_Amendment_to_the_Rehabilitation_Act_of_1973</a> &#8211; A great summary of the law, its history, and its goals.</li>
<li>
            <a target="_blank" href="http://www.access-board.gov/508.htm">http://www.access-board.gov/508.htm</a> &#8211; Another comprehensive resource detailing the law complete with a tutorial on developing accessible software</li>
<li>
            <a target="_blank" href="http://www.jimthatcher.com/sidebyside.htm">http://www.jimthatcher.com/sidebyside.htm</a> &#8211; A useful side by side comparison of Section 508 and the Web Content Accessibility Guidelines</li>
</ul>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/tips-for-making-your-website-section-508-compliant/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Introduction to the WDK Combo Container</title>
		<link>http://www.bluefishgroup.com/2008/introduction-to-wdk-combo-container/</link>
		<comments>http://www.bluefishgroup.com/2008/introduction-to-wdk-combo-container/#comments</comments>
		<pubDate>Mon, 22 Dec 2008 12:00:00 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Custom ECM Solutions]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=393</guid>
		<description><![CDATA[Overview The WDK Combo Container component is heavily utilized throughout Webtop to provide a consistent and flexible user interface for performing coordinated actions upon multiple repository objects. It is used by many of the core document actions in Webtop, such as Import, Checkout, Checkin, Cancel Checkout, Link Here, and Export, as well as other multiselect [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Overview</a><br />
    </h3>
<p>
            The WDK Combo Container component is heavily utilized throughout Webtop to provide a<br />
            consistent and flexible user interface for performing coordinated actions upon multiple repository objects.<br />
            It is used by many of the core document actions in Webtop, such as Import, Checkout, Checkin,<br />
            Cancel Checkout, Link Here, and Export, as well as other multiselect actions and use cases that are perhaps a bit<br />
            more obscure, and it can provide a robust starting point for building custom multiselect components.<br />
            The key features provided by the Combo Container are Multiselect Argument Decoding, Value Propagation,<br />
            and Auto-Commit.
        </p>
<p>
            A solid understanding of the Combo Container framework is often useful and sometimes vital when<br />
            attempting customization of that framework or any of the components which depend on it.<br />
            If one is planning to build a new custom component based directly on the Combo Container, it is even more<br />
            important to have a firm grasp of the framework&#8217;s interactions and extension points.
        </p>
<p>
            The Combo Container implementation includes several well-defined hooks and event handler methods which<br />
            subclasses can utilize to customize its behavior; however, some of these extension points are poorly<br />
            defined or even obfuscated, making it difficult to build reliable and robust custom components that<br />
            properly utilize the Combo Container.
        </p>
<p>
            The information in this article is meant to provide a high level understanding of how the various<br />
            Combo Container mechanisms function and interact, and to warn against some of the more insidious pitfalls.<br />
            It is not a detailed blueprint for customizing the framework, but rather a head start toward understanding<br />
            the overall landscape, so the reader can focus more time on implementing and less time ramping up.
        </p>
<p class="note">
        <b>Note: </b><br />
            This article was written based on Webtop 6.0 SP1.
        </p>
<h3>
        <a name="head2" class="section">WDK Context</a><br />
    </h3>
<p>
            The ID for the base Combo Container component is <code>combocontainer</code>. Its component<br />
            definition can be found at <code>/wdk/config/combocontainer_component.xml</code>. The Java<br />
            component class is located at <code>com.documentum.web.formext.component.ComboContainer</code>.
        </p>
<p>
            The Combo Container component utilizes two different JSP pages, both of which are configured in the<br />
            component XML:
        </p>
<ul>
<li>
            <b>start</b><br />
            </p>
<p>            <code>/wdk/container/combocontainer.jsp</code><br />
            </p>
<p>                Displays the current contained component and any headers, footers, etc.
            </li>
<li>
            <b>autocommit</b><br />
            </p>
<p>            <code>/wdk/container/comboautocommitex.jsp</code><br />
            </p>
<p>                Displays the progress bar and drives client-side events during auto-commit.
            </li>
</ul>
<p>
            (More on these pages later.)
        </p>
<h4>ComboContainer Type Hierarchy</h4>
<p>
            The <code>ComboContainer</code> component extends the <code>WizardContainer</code> component, and as such<br />
            inherits the behavior of <code>WizardContainer</code>, <code>DialogContainer</code>, <code>Container</code>,<br />
            <code>Component</code>, <code>Form</code>, and <code>Control</code>.
        </p>
<div align="center">
        <img src="/article-assets/images/combo-container/combo-container-type-hierarchy.jpg" border="0" alt="Fig. 1: ComboContainer Type Hierarchy">
<p class="figure">
            <b><br />
              Figure 1:<br />
            </b> ComboContainer Type Hierarchy</p>
</p></div>
<p>
        <code>Control</code>, <code>Form</code>, and <code>Component</code> provide the core functionality and<br />
            framework integration require by all WDK components.
        </p>
<p>
        <code>Container</code> provides the core WDK container capabilities, enabling the component to contain<br />
            another component.
        </p>
<p>
        <code>DialogContainer</code> provides the standard dialog UI, including the OK and Cancel buttons and their<br />
            event handlers, as well as the dialog label.
        </p>
<div align="center">
        <img src="/article-assets/images/combo-container/dialog-container-component-overview.jpg" border="0" alt="Fig. 2: DialogContainer Component Overview">
<p class="figure">
            <b><br />
              Figure 2:<br />
            </b> DialogContainer Component Overview</p>
</p></div>
<p>
        <code>WizardContainer</code> provides support for multiple contained components and UI for pagination,<br />
            including the Next and Previous buttons and their event handlers, as well as the internal state necessary<br />
            to keep track of which contained component is currently being displayed.
        </p>
<div align="center">
        <img src="/article-assets/images/combo-container/wizard-container-component-overview.jpg" border="0" alt="Fig. 3: WizardContainer Component Overview">
<p class="figure">
            <b><br />
              Figure 3:<br />
            </b> WizardContainer Component Overview</p>
</p></div>
<p>
        <code>ComboContainer</code> adds support for multiple instances of the same contained component,<br />
            and it provides a framework to coordinate and automate the behavior of those components, through<br />
            value propagation and auto-commit.
        </p>
<div align="center">
        <img src="/article-assets/images/combo-container/combo-container-component-overview.jpg" border="0" alt="Fig. 4: ComboContainer Component Overview">
<p class="figure">
            <b><br />
              Figure 4:<br />
            </b> ComboContainer Component Overview</p>
</p></div>
<h3>
        <a name="head3" class="section">Basic Mechanics</a><br />
    </h3>
<p>
            To begin, let me walk you through a short overview of the basic Combo Container mechanics.
        </p>
<p>
            The component lifecycle for the Combo Container is similar to that of the container classes it<br />
            extends, with the added dimension of multiple, indexed components. Instead of simply containing a single<br />
            component with multiple pages, as is the case for the <code>WizardContainer</code>, <code>ComboContainer</code><br />
            contains multiple, indexed instances of the same component, through which the user can move forward<br />
            and backward using the Next and Previous buttons.
        </p>
<p>
            To accomplish this, the ComboContainer maintains internal state to keep track of the array of contained<br />
            components as well as the index of the &#8220;current&#8221; component. The basic mechanics of the pagination<br />
            and containership are encapsulated by the methods described below.
        </p>
<h4>Public Methods</h4>
<ul>
<li>
            <b><code>void onInit(ArgumentList)</code></b><br />
            </p>
<p>                Called once when the container is initialized. This method sets up component state, decodes the<br />
                multiselect arguments, and initializes value propagation.
            </li>
<li>
            <b><code>boolean hasPrevPage()</code></b> and <b><code>boolean hasNextPage()</code></b><br />
            </p>
<p>                Overrides implementations inherited from <code>WizardContainer</code> in order to support multiple<br />
                indexed instances of the same component and report whether there are any more components before/after<br />
                the current one.
            </li>
<li>
            <b><code>boolean onPrevPage()</code></b> and <b><code>boolean onNextPage()</code></b><br />
            </p>
<p>                Overrides implementations inherited from <code>WizardContainer</code> to move the &#8220;current<br />
                component&#8221; index backward or forward, as appropriate. The <code>onNextPage</code> also includes<br />
                logic for stopping an auto-commit that has failed due to validation or other problems.
            </li>
<li>
            <b><code>boolean canCommitChanges()</code></b><br />
            </p>
<p>                Hard-coded in the <code>ComboContainer</code> to return <code>true</code>, this method can be overridden<br />
                to drive the visibility of the Finish button and to prevent the <code>onCommitChanges</code> method<br />
                from being called as necessary.
            </li>
<li>
            <b><code>boolean onCommitChanges()</code></b><br />
            </p>
<p>                This method encapsulates logic for saving changes across all components, and for launching the<br />
                auto-commit process for any components beyond the current one. This includes launching the<br />
                auto-commit confirmation prompt dialog, and stopping the auto-commit if any of the component<br />
                commits fail due to validation or other problems.
            </li>
</ul>
<h4>Protected Methods</h4>
<ul>
<li>
            <b><code>int getComponentCount()</code></b><br />
            </p>
<p>                Returns the number of contained components, which should match the number of items multiselected<br />
                and passed into the container. Note that this count does NOT correspond to the two JSP pages utilized<br />
                by the container (<b>start</b> and <b>autocommit</b>).
            </li>
<li>
            <b><code>int getCurrentComponent()</code></b><br />
            </p>
<p>                Returns the index of the &#8220;current&#8221; component &#8212; the one that is currently being rendered by the<br />
                container. The contained components are indexed in order, starting with 0.
            </li>
<li>
            <b><code>void setCurrentComponent(int)</code></b><br />
            </p>
<p>                Sets the current component to be the one with the given index. The contained components are indexed<br />
                in order, starting with 0.
            </li>
<li>
            <b><code>ArrayList getContainedComponents()</code></b><br />
            </p>
<p>                Returns an <code>ArrayList</code> containing the contained components, in order.
            </li>
</ul>
<h3>
        <a name="head4" class="section">Multiselect Argument Decoding</a><br />
    </h3>
<p>
            The primary use case for the Combo Container is to provide multiselect behavior for a specific contained<br />
            component. When a user makes multiple selections in the WDK UI and performs a multiselect action, the<br />
            selections are encoded and passed into the single Combo Container component. The<br />
            <code>ComboContainer</code> class&#8217;s <code>onInit</code> method then decodes these arguments and stores<br />
            them to be passed into the appropriate contained component instance upon initialization.
        </p>
<h4>How It Works</h4>
<p>
            The <code>onInit</code> method looks at the argument <code>"componentArgs"</code>, and if it begins<br />
            with the string <code>"___dmfStoredArgsKey"</code>, it calls the <code>retrieveComponentArgs</code><br />
            method to extract the array of <code>ArgumentList</code> objects to use for all contained components.
        </p>
<p>
            This feature of the Combo Container framework is fairly straightforward, but if for some reason you<br />
            must override the way that multiselect arguments are encoded, you may need to dig into the implementation<br />
            of the <code>onInit</code> method.
        </p>
<h4>Public Methods</h4>
<ul>
<li>
            <b><code>void onInit(ArgumentList)</code></b><br />
            </p>
<p>                As mentioned above, this lifecycle method decodes the <code>ArgumentList</code> array corresponding<br />
                to the multiple contained component instances, based on the encoded <code>String[]</code> returned<br />
                by the  <code>retrieveComponentArgs</code> method.
            </li>
<li>
            <b><code>String[] retrieveComponentArgs(String strUniqueComponentArgsKey)</code></b><br />
            </p>
<p>                Extracts the arguments for the contained components from the Session. This static method is called<br />
                by the <code>onInit</code> method to get the encoded argument data out of the user&#8217;s Session.<br />
                This method is static and cannot be overridden. To provide custom decoding, you may need to<br />
                override the <code>onInit</code> and/or <code>setContainedComponentArgs</code> methods. (See below.)
            </li>
</ul>
<h4>Protected Methods</h4>
<ul>
<li>
            <b><code>ArgumentList[] getContainedComponentArgs()</code></b><br />
            </p>
<p>                Returns an array of <code>ArgumentList</code> objects corresponding to the arguments for each of the contained<br />
                components. The size of the array corresponds to the number of items selected &#8212; i.e. the number of<br />
                contained components.
            </li>
<li>
            <b><code>void setContainedComponentArgs(ArgumentList[])</code></b><br />
            </p>
<p>                Sets the array of <code>ArgumentList</code> objects described above. This method is called by the <code>ComboContainer</code><br />
                code to set the argument array, and so can be a useful extension point for intercepting or modifying<br />
                this behavior, or for using your own <code>ArgumentList</code> array instead of the one decoded by the ComboContainer<br />
                <code>onInit</code> and <code>retrieveComponentArgs</code> methods.
            </li>
</ul>
<p class="note">
        <b>Note: </b><br />
            It is important to recognize that the number of component instances created depends entirely on the size<br />
            of the <code>ArgumentList</code> array passed into <code>setContainedComponentArgs</code>.<br />
            <code>ComboContainer</code> uses this array to drive its instantiation of the contained component instances.
        </p>
<h3>
        <a name="head5" class="section">Value Propagation</a><br />
    </h3>
<p>
            One of the key features of the Combo Container is value propagation. Value propagation is the mechanism<br />
            by which the control values on the previous contained component are used to pre-populate the<br />
            control values for the current contained component when it is first initialized, thereby propagating<br />
            those values from one component to the next and saving the user the trouble of entering the same<br />
            values over and over.
        </p>
<h4>Configuration</h4>
<p>
            Value propagation can be enabled within the component XML by setting the value of the<br />
            <code>propagatepreviouspagevalues</code> element to <code>true</code>. Note that this configuration element<br />
            only enables or disables value propagation when the user is manually moving through the contained<br />
            components. If the user triggers an auto-commit using the Finish button, this configuration is ignored and<br />
            value propagation is always used to populate the remaining components.
        </p>
<h4>How It Works</h4>
<p>
            The full mechanics of value propagation are mostly obfuscated, but at its core the mechanism works<br />
            as follows. When <code>ComboContainer</code> is first initialized, it registers itself as a control<br />
            listener, so that any time a control is initialized by a contained component, it will trigger the<br />
            <code>onControlInitialized</code> method of <code>ComboContainer</code>.
        </p>
<p>
            When the first contained component is initialized, the controls are initialized but nothing special<br />
            happens. When the form is submitted, control state is updated based on the values in the request<br />
            using the <code>updateStateFromRequest</code> method. This method keeps track of any controls whose<br />
            values have changed (using <code>Control.hasChanged</code>), so they can be propagated to the next<br />
            component if necessary. These changed controls are known as the &#8220;propagation controls&#8221;.
        </p>
<p>
            When the second component is initialized, the <code>onControlInitialized</code> hook looks at each control<br />
            as it is initialized and decides whether it is a candidate for value propagation. In order for a control<br />
            to be such a candidate, the container must have a similar control in its &#8220;propagation controls&#8221; set described<br />
            above. In this case, &#8220;similar&#8221; means the controls share the same name, type, and index. If the control<br />
            is a candidate for value propagation, the value is propagated, assuming propagation is supported for<br />
            that type of control. (See below.)
        </p>
<p>
            It is important to note that only certain types of controls are supported by value propagation.<br />
            Specifically, the <code>ComboContainer.onControlInitialized</code> method has logic to recognize<br />
            and propagate the value of any control that has bean methods for getting and setting that value,<br />
            as long as those method signatures are of the form <code>T getValue()</code> and<br />
            <code>void setValue(T)</code>, where <code>T</code> is the value type. The ComboContainer class has<br />
            additional logic for dealing specifically with <code>DateTime</code> controls, which don&#8217;t conform to<br />
            the signatures above, and <code>DocbaseAttribute</code> and <code>DocbaseAttributeValue</code> controls<br />
            (and their subclasses), which require special processing.
        </p>
<p>
            Fortunately, most controls extend from <code>StringInputControl</code>, which has the necessary bean<br />
            methods and therefore meets the criteria for value propagation. Unfortunately, some controls do not<br />
            have bean methods conforming to the method signatures described above, and therefore value propagation<br />
            is not supported for these controls. This can be problematic, most notably in the case of the<br />
            <code>Checkbox</code> and <code>Radio</code> controls. As of Webtop 6.0 SP1, any value propagation that<br />
            is required for these types of controls must be implemented as a customization.
        </p>
<p class="note">
        <b>Note: </b><br />
            In order for value propagation to work, each control must actually be rendered by the WDK presentation<br />
            engine. This requires each component&#8217;s JSP page to be triggered, which is fine if the user is manually<br />
            paging through the components; however, the situation is not so simple during an auto-commit.
        </p>
<p class="note">
        <b>Note: </b><br />
            The &#8220;propagation controls&#8221; set is stateful for all contained components, which means that if a control is<br />
            changed in the first component, then not changed in the second component, that control is still available<br />
            for propagation to the third component.
        </p>
<h4>Public Methods</h4>
<ul>
<li>
            <b><code>void onControlInitialized(Form, Control)</code></b><br />
            </p>
<p>                Called for each control contained by the container as the control is initialized<br />
                (recursively into the contained components). This is the hook by which the value propagation<br />
                occurs for each contained control as appropriate. This is also where the custom logic for<br />
                handling <code>DateTime</code>, <code>DocbaseAttribute</code>, and <code>DocbaseAttributeValue</code><br />
                classes  can be found. This method provides a useful extension point for adding value propagation<br />
                support for new Control types. The biggest challenge is being certain to use the same logic as the<br />
                <code>ComboContainer</code> class for determining whether to propagate the value or not.
            </li>
<li>
            <b><code>void updateStateFromRequest()</code></b><br />
            </p>
<p>                Standard component lifecycle method, used to update component state based on data in the Request.<br />
                This method calls out to the private method <code>updatePropagationControls</code> in order to<br />
                acquire handles to any controls whose values have changed and therefore need to be tracked for<br />
                purposes of value propagation. This is the &#8220;propagation controls&#8221; set described above.
            </li>
<li>
            <b><code>boolean isValueSetByPropagation(Control)</code></b><br />
            </p>
<p>                Returns <code>true</code> if the an auto-commit is active and if the given control is one whose<br />
                value can be set based on the previous component using value propagation; in other words, if a similar<br />
                control can be found in the &#8220;propagation control&#8221; set stored as part of the <code>ComboContainer</code><br />
                state.
            </li>
</ul>
<h4>Protected Methods</h4>
<ul>
<li>
            <b><code>void setPropagatePreviousPageValues(boolean)</code></b><br />
            </p>
<p>                Sets the boolean flag indicating whether or not the previous component&#8217;s values should be propagated<br />
                to the current component when it is initialized. This method is called by the private method<br />
                <code>initPropagatePreviousPageValues</code> (see below) based on the value configured in<br />
                the component XML. This method can be called any time after the <code>onInit</code> method in order to<br />
                override the configured behavior. In addition, this method is called by the auto-commit code<br />
                in order to turn on value propagation regardless of configuration. (More on that later.)
            </li>
<li>
            <b><code>boolean isPropagatePreviousPageValues()</code></b><br />
            </p>
<p>                Returns the value of the flag described above. This method is called from <code>onControlInitialized</code><br />
                in order to determine whether or not to execute the value propagation logic when a new control is<br />
                initialized.
            </li>
<li>
            <b><code>void propagateAdditionalProperties(Control, Control)</code></b><br />
            </p>
<p>                Propagates configuration elements and other properties from one control to the other. Presumably<br />
                this is necessary in order for certain contained component instances to function properly. This method<br />
                is called from <code>onControlInitialized</code> as well.
            </li>
</ul>
<h4>Private Methods</h4>
<p>
            Although private methods cannot be overridden, understanding them can provide useful context.
        </p>
<ul>
<li>
            <b><code>void updatePropagationControls()</code></b><br />
            </p>
<p>                Called from <code>updateStateFromRequest</code>, this method scans all contained controls recursively<br />
                looking for any that have changed, so that these can be added to the internal hash of controls whose<br />
                values can be propagated. This is part of the internal value propagation state management, and cannot<br />
                be overridden, but it is useful to provide context for what goes on &#8220;inside the black box&#8221;.
            </li>
<li>
            <b><code>void initDocbaseAttributeControls(Control)</code></b><br />
            </p>
<p>                Called from <code>onControlInitialized</code> when a <code>DocbaseAttribute</code> or<br />
                <code>DocbaseAttributeValue</code> control is initialized (assuming value propagation is<br />
                enabled and there is a value to propagate). This internal method propagates additional state<br />
                from one <code>DocbaseAttribute</code> or <code>DocbaseAttributeValue</code> control to another;<br />
                is called at the end of <code>onControlInitialized</code> after the basic value propagation logic<br />
                has occurred.
            </li>
<li>
            <b><code>void initPropagatePreviousPageValues()</code></b><br />
            </p>
<p>                Sets the flag indicating whether value propagation is enabled, based on the<br />
                <code>propagatepreviouspagevalues</code> element in the component configuration.<br />
                This private method is called from <code>onInit</code> to set the flag initially, and it is also<br />
                called the <code>stopAutoCommit</code> method to reset the value propagation flag when<br />
                an auto-commit is stopped. (More on this below.)
            </li>
</ul>
<h3>
        <a name="head6" class="section">Auto-Commit</a><br />
    </h3>
<p>
            When performing an action on multiple repository objects using the Combo Container, it is often<br />
            the case that the same attributes can be applied to all objects. Manually paging through the<br />
            components and entering the same metadata again and again can be time-consuming and error-prone.<br />
            Fortunately, the Combo Container has a solution to this problem, in the form of the auto-commit<br />
            mechanism.
        </p>
<p>
            The auto-commit mechanism is triggered by the Finish button, and it is responsible for driving automated<br />
            cycling through the Combo Container&#8217;s contained components. This cycling relies on a delicate coordination<br />
            of server- and client-side events which ensure that every contained component is properly initialized and<br />
            rendered (though not displayed), and validated, before ultimately committing all components.
        </p>
<p class="note">
        <b>Note: </b><br />
            It is critical that this automated request cycling occur. Not only is this the means by which the<br />
            user can track the progress of the auto-commit (by way of the progress bar), but it is also the only<br />
            way to guarantee that the value propagation logic functions properly, which is usually necessary for<br />
            the auto-commit to get past validation.
        </p>
<div align="center">
        <img src="/article-assets/images/combo-container/combo-container-autocommit-interactions.jpg" border="0" alt="Fig. 5: Combo Container Auto-Commit Interactions">
<p class="figure">
            <b><br />
              Figure 5:<br />
            </b> Combo Container Auto-Commit Interactions</p>
</p></div>
<h4>Configuration</h4>
<p>
            None of the auto-commit behavior is configurable as part of the base <code>combocontainer</code><br />
            component XML. As previously described, the only way to disable auto-commit is via the visibility<br />
            of the Finish button, which can be driven using the <code>canCommitChanges</code> method or by<br />
            setting the visibility of the Finish button directly.
        </p>
<h4>How It Works</h4>
<p>
            When a user clicks on the Finish button, it triggers the <code>onOk</code> event handler method<br />
            from <code>DialogContainer</code>.</p>
<p>            This method first calls <code>canCommitChanges</code>, which is hard-coded in <code>ComboContainer</code><br />
            to return <code>true</code>. Then it calls <code>onCommitChanges</code>, which calls<br />
            <code>hasNextPage</code> to determine whether there are any components beyond the current one.</p>
<p>            If the <code>hasNextPage</code> method reports that there are additional components remaining after<br />
            the current one, then the current component is validated, and it is found to be valid, the auto-commit<br />
            mechanism is triggered.
        </p>
<p>
            First, the <code>showConfirmPrompt</code> method is called to ascertain whether the confirmation prompt<br />
            should be shown. If no confirmation is needed, the <code>startAutoCommit</code> method is called<br />
            immediately. Otherwise, the component nests to the prompt component to display the auto-commit confirmation<br />
            prompt, then triggers the <code>onReturn</code> method when it returns, which calls<br />
            <code>startAutoCommit</code> or not, depending on the user&#8217;s response.
        </p>
<p class="note">
        <b>Note: </b><br />
            The confirmation prompt can be disabled by the user through a user preference, in which case the<br />
            <code>showConfirmationPrompt</code> method would return <code>false</code>.
        </p>
<p>
            The <code>startAutoCommit</code> method overrides any configured value propagation flag, enabling value<br />
            propagation for the duration of the auto-commit process. It then switches the ComboContainer component&#8217;s<br />
            current page from the <code>start</code> page (used to display the contained component) to the<br />
            <code>autocommit</code> page, which is used to display the progress bar and to drive the client-side<br />
            events required to automate the request cycle. Finally, it sets the client event <code>onPostAutoCommitEvent</code><br />
            to be triggered client-side when the page is rendered in the user&#8217;r broswer.
        </p>
<p>
            The behavior of <code>onPostAutoCommitEvent</code> client-side event depends on the value of the<br />
            JavaScript variable <code>g_strAutoCommitEvent</code>, which is set inside the <code>onRenderEnd</code><br />
            method by appending some JavaScript code to the page. The value of this variable is used to tell<br />
            the client-side event which server-side event it must trigger to continue the auto-commit processing<br />
            as appropriate. The <code>onRenderEnd</code> method gets the value for this variable from the<br />
            private method <code>getAutoCommitEvent</code>.
        </p>
<p>
            The <code>getAutoCommitEvent</code>, although private, is critical. It is here that the auto-commit<br />
            mechanism&#8217;s core logic resides. As the automated cycling proceeds, this method gets called repeatedly<br />
            to automatically trigger the multiple <code>onNext</code> events necessary for paging through the<br />
            contained components, the <code>onStopAutoCommit</code> event if something goes wrong, and the<br />
            <code>onOk</code> event that it ultimately calls once it has cycled through all the contained<br />
            components.
        </p>
<p class="note">
        <b>Note: </b><br />
            Unfortunately, the <code>getAutoCommitEvent</code> is private and therefore cannot be overridden.<br />
            If it becomes necessary to customize the auto-commit interactions, the best approach is usually to<br />
            start with the standard component lifecycle methods, where you can sometimes &#8220;correct&#8221; or &#8220;undo&#8221;<br />
            changes made internally by the private Combo Container code. Use extreme caution when modifying<br />
            auto-commit interactions, as it is very easy to break the framework entirely.
        </p>
<p>
            As the framework cycles automatically through the contained components, the <code>onNextPage</code><br />
            method is utilized by the <code>onNext</code> event handler in order to move the &#8220;current&#8221; component<br />
            forward. If it encounters any trouble due to validation, the &#8220;stoppingAutoCommit&#8221; flag is set, which<br />
            will ultimately lead the <code>getAutoCommitEvent</code> method to trigger a client-side event to<br />
            stop the auto-commit. But if the <code>onNext</code> calls succeed, eventually the framework runs out<br />
            of contained components, and at this point (when <code>hasNextPage</code> returns <code>false</code>,<br />
            the <code>getAutoCommitEvent</code> method triggers the <code>onOk</code> event handler, which, as<br />
            described above, calls <code>onCommitChanges</code>.
        </p>
<p>
            At this point, the <code>onCommitChanges</code> method recognizes that there are no more remaining<br />
            components to visit, and so it proceeds to call each contained component&#8217;s <code>onCommitChanges</code><br />
            method. If anything goes wrong, the component is displayed along with the error; otherwise, the commit<br />
            has succeeded and the component returns to the context from which it was originally called!
        </p>
<h4>Public Methods</h4>
<ul>
<li>
            <b><code>void onReturn(Form, Map)</code></b><br />
            </p>
<p>                This is the event handler which processes the return from nest to the auto-commit confirmation prompt.
            </li>
<li>
            <b><code>boolean inAutoCommit()</code></b><br />
            </p>
<p>                Reports whether an auto-commit is currently active, which is true if the current container<br />
                page is the <code>autocommit</code> page and whether the internal &#8220;stoppingAutoCommit&#8221; flag<br />
                has not been set.
            </li>
<li>
            <b><code>void onRenderEnd()</code></b><br />
            </p>
<p>                If an auto-commit is active, this method appends the JavaScript necessary to trigger any<br />
                client-side events.
            </li>
<li>
            <b><code>void pauseAutoCommit()</code></b><br />
            </p>
<p>                This method sets a flag indicating that the auto-commit should be paused. If set, this flag will<br />
                be picked up when <code>onRenderEnd</code> calls <code>getAutoCommitEvent</code>, which will<br />
                interrupt (i.e. pause) the automated request cycling.
            </li>
<li>
            <b><code>void resumeAutoCommit()</code></b><br />
            </p>
<p>                This method resets the auto-commit pause flag so that the auto-commit can resume.
            </li>
<li>
            <b><code>void onStopAutoCommit(Control, ArgumentList)</code></b><br />
            </p>
<p>                This event handler method handles the <code>onStopAutoCommit</code> event, triggered client-side in<br />
                response to a client-side event triggered by <code>onRenderEnd</code> and<br />
                <code>getAutoCommitEvent</code> in response to the &#8220;stoppingAutoCommit&#8221; flag.<br />
                This method first calls the <code>stopAutoCommit</code> method to update internal<br />
                container state, then it calls the <code>stoppingAutoCommit</code> method to clear the<br />
                &#8220;stoppingAutoCommit&#8221; flag.
            </li>
</ul>
<h4>Protected Methods</h4>
<ul>
<li>
            <b><code>boolean showConfirmPrompt()</code></b><br />
            </p>
<p>                Checks the user preference to determine whether the auto-commit confirmation prompt should be displayed.<br />
                Checked by <code>onCommitChanges</code> prior to launching an auto-commit.
            </li>
<li>
            <b><code>void inhibitConfirmPrompt()</code></b><br />
            </p>
<p>                Sets the user preference to prevent the auto-commit confirmation prompt from being displayed. This is<br />
                called by <code>onReturn</code> if the user has chosen to hide the confirmation prompt in the future.
            </li>
<li>
            <b><code>void startAutoCommit()</code></b><br />
            </p>
<p>                This method launches the auto-commit process. It is called from <code>onReturn</code><br />
                if the confirmation prompt was shown, or directly from <code>onCommitChanges</code> if it wasn&#8217;t.
            </li>
<li>
            <b><code>void stopAutoCommit()</code></b><br />
            </p>
<p>                Called by the <code>onStopAutoCommit</code> event handler described above, this method actually<br />
                updates the internal auto-commit mechanism state to prevent the auto-commit from continuing, as<br />
                is necessary in the case of validation or other errors. It sets the container page back to the<br />
                <code>start</code> page, so that the contained component can be displayed instead of the<br />
                progress bar, at which point auto-commit cycling ceases.
            </li>
<li>
            <b><code>void stoppingAutoCommit(boolean)</code></b><br />
            </p>
<p>                Sets the <code>stoppingAutoCommit</code> flag.
            </li>
</ul>
<h4>Private Methods</h4>
<p>
            Although private methods cannot be overridden, understanding them can provide useful context.
        </p>
<ul>
<li>
            <b><code>String getAutoCommitEvent</code></b><br />
            </p>
<p>                Determines which client-side event should be triggered, based on the current auto-commit flags<br />
                and container state.
            </li>
</ul>
<h3>
        <a name="head7" class="section">Tips and Pitfalls</a><br />
    </h3>
<h4>Trace Logging</h4>
<p>
            Some of the Combo Container behavior can be observed by turning on the trace logging for<br />
            <code>com.documentum.web.formext.Trace.COMBOCONTAINER</code> using either <code>TraceProp.properties</code><br />
            or <code>tracing.jsp</code>. The trace logging is minimal, but it&#8217;s still worth enabling.
        </p>
<h4>Finish Button Visibility</h4>
<p>
            The best way to drive the visibility of the Finish button is through the use of the <code>canCommitChanges</code><br />
            method, which is hard-coded to return <code>true</code> in ComboContainer but can be overridden. It is<br />
            also possible to acquire the Finish button control and set its visibility directly, but this must be done<br />
            after <code>updateControls</code> is called, since it will reset the visibility based on the <code>canCommitChanges</code><br />
            method.
        </p>
<h4>Custom Value Propagation</h4>
<p>
            As described earlier, the value propagation mechanisms found in the Combo Container framework only<br />
            work for certain controls &#8212; those that have getValue/setValue bean methods, and DateTime.<br />
            In order to propagate state not stored in such controls, it may be necessary to override some<br />
            of the value propagation and component lifecycle methods described above.
        </p>
<p>
            The <code>onNextPage</code> method can provide a useful place to identify controls whose values were not<br />
            propagated during an auto-commit and handle them appropriately. However, when implementing your own value<br />
            propagation that works during manual pagination as well as auto-commit, it is usually necessary to<br />
            override one or more of the lifecycle methods, such as <code>updateStateFromRequest</code>,<br />
            <code>onControlInitialized</code>, or <code>onInit</code>,  in order to track the new component types<br />
            and propagate values from the previous component to the current one.
        </p>
<p>
            Remember that value propagation can be tested by enabling it explicitly in the Combo Container component&#8217;s<br />
            configuration. This makes it possible to observe and verify the value propagation behavior by manually<br />
            stepping through the components, rather than having to use auto-commit to trigger value propagation, which<br />
            can much more difficult to trace.
        </p>
<p class="note">
        <b>Note: </b><br />
            Use caution when overriding value propagation methods and behavior! Use logging judiciously in your<br />
            custom code to help trace event handlers and state changes.
        </p>
<h4>Multi-Page Components</h4>
<p>
            Think twice before using a multi-page component as your contained component.
        </p>
<p>
            The <code>ComboContainer.onNextPage</code> method is responsible for moving from one page of a component<br />
            to the next. This method inherits some behavior from <code>WizardContainer.onNextPage</code>, which<br />
            actually calls into the <code>onNextPage</code> method of the contained component. Ditto for <code>onPrevPage</code>.<br />
            It therefore appears to be feasible to customize the contained component to contain multiple pages itself &#8212;<br />
            multiple tabs, for example &#8212; and to use the <code>onNextPage</code> and <code>onPrevPage</code> hooks<br />
            to drive value propagation and auto-commit behavior.
        </p>
<p>
            This approach is certainly possible, but there are many hazards, due to the way the Combo Container<br />
            functions. The auto-commit methods drive an active cycling of client-side and server-side activity. This request<br />
            cycling is coordinated by the auto-commit state and methods, and it ensures full initialization of every<br />
            contained component page. Proper cycling depends on the way the pagination logic interprets return values<br />
            from methods such as <code>hasNextPage</code>, <code>onNextPage</code>, <code>canCommitChanges</code>, and the like.
        </p>
<p>
            Successful integration often requires careful engineering of the <code>onNextPage</code> method to enable proper<br />
            cycling through component pages without the auto-commit mechanism stalling. In rare cases, careful<br />
            customization of the auto-commit methods or manipulation of internal auto-commit state may be<br />
            necessary as well.
        </p>
<p>
            In some cases, it may even be necessary to override the auto-commit state changes in order to &#8220;fool&#8221; the<br />
            auto-commit logic into continuing to the next page or component as needed. Caution, testing, logging,<br />
            and a decompiler can be your friends in these situations.
        </p>
<p class="note">
        <b>Note: </b><br />
            If multi-page logic is necessary in your contained component, it should extend <code>WizardContainer</code><br />
            if at all possible. Extensive testing is recommended regardless, as the auto-commit mechanism may not<br />
            play nicely with certain customizations.
        </p>
<h3>
        <a name="head8" class="section">Summary</a><br />
    </h3>
<p>
            The WDK Combo Container framework provides a flexible, extensible mechanism for driving multiple<br />
            instances of the same component in response to a multiselect action. Although customization can be<br />
            dangerous, with the right context and careful planning, the framework can be adapted to a wide array<br />
            of situations.
        </p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/introduction-to-wdk-combo-container/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>New Article: Resilient Documentum Workflow Integration with Automated Recovery</title>
		<link>http://www.bluefishgroup.com/2008/new-article-resilient-documentum-workflow-integration-with-automated-recovery/</link>
		<comments>http://www.bluefishgroup.com/2008/new-article-resilient-documentum-workflow-integration-with-automated-recovery/#comments</comments>
		<pubDate>Sat, 13 Dec 2008 20:29:15 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=391</guid>
		<description><![CDATA[Have you ever had a Documentum end-user ask you to check on a document because they launched it on a workflow and no one seems to have it in their inbox? Often when this happens, it&#8217;s because the workflow had an error along the way and is stuck in a paused state, requiring an administrator [...]]]></description>
				<content:encoded><![CDATA[<p>Have you ever had a Documentum end-user ask you to check on a document because they launched it on a workflow and no one seems to have it in their inbox? Often when this happens, it&#8217;s because the workflow had an error along the way and is stuck in a paused state, requiring an administrator to manually intervene and resume the workflow. If your Documentum administrators are as busy as the ones I know, the last thing they have time for is baby sitting workflows. </p>
<p>Jamie Balling, one of the Technical Leads here at Blue Fish, developed an application that automatically detects paused workflows and automatically resumes them, freeing up the support team to focus on real fires. He just wrote a great article that describes the program, complete with sample code.</p>
<p>Learn more by reading <a href="/library/2008/automated-workflow-recovery/">Resilient Documentum Workflow Integration with Automated Recovery</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/new-article-resilient-documentum-workflow-integration-with-automated-recovery/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Resilient Documentum Workflow Integration with Automated Recovery</title>
		<link>http://www.bluefishgroup.com/2008/automated-workflow-recovery/</link>
		<comments>http://www.bluefishgroup.com/2008/automated-workflow-recovery/#comments</comments>
		<pubDate>Fri, 12 Dec 2008 12:00:00 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Custom ECM Solutions]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=384</guid>
		<description><![CDATA[Overview In my last article, I discussed how to monitor services and integration points for a complex Documentum based application. In this article, I turn my attention to strategies we employed to make our workflow integration more resilient to problems that might be encountered. This article will have a more technical focus. In our experience, [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Overview</a><br />
    </h3>
<p>In my last article, I discussed how to monitor services and integration points for a complex Documentum based application. In this article, I turn my attention to strategies we employed to make our workflow integration more resilient to problems that might be encountered. This article will have a more technical focus.</p>
<p>In our experience, portions of the Documentum workflows subsystem &#8211; namely, the Java Method Server &#8211; can sometimes unexpectedly become unresponsive.  The monitoring solution described in the previous article works well at catching this problem and routing it to the support team to give it a &#8220;kick.&#8221;  Unfortunately, any documents which are submitted during the method server outage can become stuck in paused workflows which can prevent users from seeing their tasks. To recover from situations like this, we have implemented a &#8220;workflow recovery poller&#8221; that finds and restarts affected workflows.</p>
<h3>
        <a name="head2" class="section">Documentum Workflow Objects Primer</a><br />
    </h3>
<p>Before getting into the details of our solution, we need to provide some background by covering the key Documentum workflow objects and their relationships. You can refer to the <i>Documentum Object Reference</i> for additional information.</p>
<p>    <strong>Process (dm_process)</strong></p>
<p>A workflow is really a just a process and Documentum has a &#8220;process&#8221; object which models the steps. This object is really a template and you can think of each workflow as a specific instance following the steps of that template. Note that these processes can be created and managed with EMC&#8217;s Documentum products such as <i>Workflow Manager</i> and <i>Business Process Manager</i>.</p>
<p>    <strong>Activity (dm_activity)</strong><br />
    </p>
<p>There is an &#8220;activity&#8221; object for each step of the process. The process object has a repeating attribute (r_act_name) which lists the names of each activity in the template. There are also related repeating attributes which describe other attributes of each activity.</p>
<p>    <strong>Workflow (dm_workflow)</strong><br />
    </p>
<p>The &#8220;workflow&#8221; object captures the state of a document (or group of documents) going through the steps of a process template. This object has an overall status which is captured using the field <strong>&#8220;r_runtime_state&#8221;</strong>. The valid values for runtime state are:</p>
<p>    <code><br />
		DF_WF_STATE_UNKNOWN = -1</p>
<p>		DF_WF_STATE_DORMANT = 0</p>
<p>		DF_WF_STATE_RUNNING = 1</p>
<p>		DF_WF_STATE_FINISHED = 2</p>
<p>		DF_WF_STATE_HALTED = 3</p>
<p>		DF_WF_STATE_TERMINATED = 4</p>
<p>    </code><br />
    </p>
<p>In addition to this overall state, each individual activity in the process template has a state. These are captured in the repeating attribute <strong>&#8220;r_act_state&#8221;</strong>. The valid values for activity state are:</p>
<p>    <code><br />
		DF_ACT_STATE_UNKNOWN = -1</p>
<p>		DF_ACT_STATE_DORMANT = 0</p>
<p>		DF_ACT_STATE_ACTIVE = 1</p>
<p>		DF_ACT_STATE_FINISHED = 2</p>
<p>		DF_ACT_STATE_HALTED = 3</p>
<p>		DF_ACT_STATE_FAILED = 4</p>
<p>    </code><br />
    </p>
<p>Documentum updates the status of the workflow and activities as the workflow progresses. If an activity fails, for example, the r_act_state will show a value of &#8220;4&#8243;.</p>
<p>    <strong>Package (dmi_package)</strong></p>
<p>The workflow object doesn&#8217;t have any fields to relate it to the document(s) with which it is associated. This is the job of the &#8220;package&#8221; object. Each package references the id of the workflow and has a repeating attribute (called r_component_id) which contains the object ids of the content associated with that workflow.</p>
<p>    <strong>Work Item (dmi_workitem)</strong></p>
<p>Each activity for a workflow can have multiple performers and there are associated &#8220;work items&#8221; for each of them. The work item captures details (such as due date) about that activity for that performer. Each work item has a field (r_queue_item_id) which is used to associate it with a &#8220;queue item&#8221; in the user&#8217;s inbox.</p>
<p>    <strong>Queue Item (dmi_queue_item)</strong></p>
<p>&#8220;Queue items&#8221; are Documentum constructs which are used to preset items in the user&#8217;s inbox queue. Queue items are not workflow specific objects, but there will be one associated with each work item.</p>
<h3>
        <a name="head3" class="section">Workflow Design</a><br />
    </h3>
<p>We have brushed up on the key Documentum workflow objects, but we aren&#8217;t quite ready to jump into the details of our workflow recovery implementation. There isn&#8217;t a &#8220;one size fits all&#8221; implementation, because a successful strategy depends on the specifics of the workflow process design. In order to demonstrate the implementation, we will use a simplified version of our process template.</p>
<p>The end goal of our workflow is to ensure that a document gets the appropriate reviews so that it can be made active to end users. We have an automated workflow activity which inspects custom attributes on the document to determine the appropriate reviewer and creates review tasks. Note that this activity re-runs whenever a task is completed so that we can re-evaluate the status.</p>
<p>All of our documents go through workflow when they are uploaded. Documents initially have a version label of &#8220;pending&#8221;, and once the classifications are approved, we replace that label with &#8220;active&#8221; which indicates that the document can go live.</p>
<h3>
        <a name="head4" class="section">Workflow Recovery Implementation</a><br />
    </h3>
<p>Now that we have covered the details of our workflow implementation, we can discuss the strategy to recover from outages. As mentioned above, we have experienced times when the Java Method Server becomes unresponsive. When this is happening and new documents are imported (or outstanding review tasks are acted upon), the workflow activities fail and the documents become &#8220;stuck&#8221; in a pending state. Our solution was to introduce a process which runs regularly to find and fix workflows which aren&#8217;t in a valid state.</p>
<p>Given the business requirements of our system, we decided to keep the logic simple and kick off a new workflow when a document is in an invalid state. This works for us because our aforementioned automated review activity will inspect the status of previously processed documents and act appropriately. However, the same concepts could be used to restart workflows anywhere in the process flow.</p>
<p>Our process is a standalone java application that runs every 5 minutes. It utilizes a framework for running periodic tasks which is part or our solution, but could also have been implemented utilizing standard Documentum job scheduling. At a high level, the process finds any failed workflows by looking at state codes on the workflow object, deleting these failed workflows, and then starting a new one for any pending document (without a workflow). The detailed code, which utilizes <i>Documentum Foundation Classes</i> (DFC), follows:</p>
<ol>
<li>
<p>
                <strong>Delete any halted workflows</strong> (note that when a running workflow fails, Documentum can put that workflow in a halted state).</p>
<p>We identify these workflow objects using a DQL query:</p>
<p>                <code>SELECT r_object_id FROM dm_workflow w WHERE w.r_runtime_state=3</code>
            </p>
<p>We then iterate over the returned objects and abort the workflows using DFC:</p>
<pre>
                <code>
IDfWorkflow workflow = (IDfWorkflow)session.getObject(new DfId(workflowId));
if (!workflow.isDeleted() 
             &amp;&amp; workflow.getRuntimeState()!=IDfWorkflow.DF_WF_STATE_TERMINATED) {
    workflow.abort();
}
</code>
            </pre>
</li>
<li>
<p>
                <strong>Delete any workflow with a halted or failed activity.</strong> Note that this is different than item 1 because the overall workflow runtime state can show as &#8220;running&#8221; even though there is a failed activity.</p>
<p>We identify these workflow objects using a DQL query:</p>
<p>                <code>SELECT r_object_id FROM dm_workflow w WHERE any w.r_act_state in (3,4)</code>
            </p>
<p>We then iterate over the returned objects using the same logic described in step 1.</p>
</li>
<li>
<p>
                <strong>Now that we have deleted any halted workflows, we find all the &#8220;pending&#8221; documents which don&#8217;t have an associated workflow and start one.</strong> This works for us because all of our documents go through a workflow and it is a straightforward way to cover the various failure scenarios. If this wasn&#8217;t the case, we would have implemented logic to keep track of the documents for which workflows were deleted and act on those.</p>
<p>We utilize DQL queries executed via DFC to locate the documents in question:</p>
<p>                <code><br />
SELECT DISTINCT r_object_id FROM dm_document d<br />
WHERE ANY r_version_label = 'PENDING' and r_object_id not in<br />
          (SELECT DISTINCT d.r_object_id FROM dmi_package p, dm_workflow w, dm_document d<br />
           WHERE ANY r_component_id = d.r_object_id AND p.r_workflow_id=w.r_object_id AND w.r_runtime_state &lt;=1)<br />
</code>
            </p>
<p></p>
<p>            <strong>Note:</strong><i>This query locates documents with our &#8216;PENDING&#8217; version label and then performs a sub-select to only return those which don&#8217;t have a workflow. We determine which documents have active workflows by referencing the document&#8217;s r_object_id with the r_component_id repeating attribute on the dmi_package table, which we then join on r_workflow_id  to the workflow table to limit results to active runtime states.</i></p>
<p>We then loop through each of these documents and execute DFC methods to start a new workflow. Below are the key API calls executed for each document. Note that there are also calls to utility methods which are show after the main code block. We assume that your logic would provide variables, methods, and values which appear in blue.</p>
<pre>
                <code>
// Instantiate a workflow. Note that you can also use an "IDfWorkflowBuilder" 
// object to simplify this, but our approach gives you more flexibility (e.g.
// to set the workflow name and supervisor name).
IDfWorkflow wf = (IDfWorkflow) session.newObject("dm_workflow");

// Set the workflow name
wf.setObjectName("workflow for document");

// Get the id for the associated process template
// this example assumes you write some logic to get the process by name
// (e.g. select r_object_id from dm_process where object_name='xyz')
String processId = getProcessIdByName("some process template");

// Set the process id on the workflow
wf.setProcessId(new DfId(processId));

// Set the supervisor
wf.setSupervisorName(supervisorName);

// Save the workflow to the repository
wf.save();

// Now start the workflow as this doesn't happen by simply saving it.
// We don't set any "performers" because there is an automated activity in our
// workflow which does this. If you need it, use wf.setPerformers()
wf.execute();

// Even though we have executed this workflow, the start activity will not 
// become active until we attach a package because our start activity
// has an "input port" which means it requires a package as input. So we
// create a package with a document...

IDfList objectIds = new DfList();
objectIds.append(new DfId(documentId));

// Get the starting activity
IDfActitivty startActivity = getStartActivity(processId);

// Now lookup the name for activity rather than using the name on the 
// IDfActivity object since it might be different due to
// a known idiosyncracy 
String startActivityName = getActivityName(process,startActivity);

// Add a package to the workflow to associate the document with it
IDfId pkgId = wf.addPackage(startActivityName, 
                            getInputPort(startActivity),
                            getInputPackageName(startActivity), 
                            "dm_document",
                            null,      // not using a "note"
                            false,     // for our example
                            objectIds);

// End of processing... we now have an active workflow!
</code>
            </pre>
<p>The following utility method gets the starting activity for a workflow by looking for an activity type of &#8220;1&#8243; which indicates that it is a start activity.</p>
<pre>
                <code>
public static IDfActivity getStartActivity(String processId) 
                                           throws DfException {
    IDfProcess process = (IDfProcess)session.getObject(new DfId(processId));
    int activityCount = process.getActivityCount();
    // Iterate over the activities looking for the start activity
    for (int i = 0; i &lt; activityCount; i++) {
        if (process.getActivityType(i) == 1) {  // 1=start activity
            IDfId activityId = process.getActivityDefId(i);
            return (IDfActivity)process.getSession().getObject(activityId);
        }
    }
    return null;
}
</code>
            </pre>
<p>This utility method gets the name of the passed activity. <i>Note that the Documentum workflow applications will not update the name of existing activity objects if it is changed. Therefore, we always refer back to the process object to get the name.</i>
            </p>
<pre>
                <code>
public static String getActivityName(IDfProcess process, IDfActivity activity)
                                     throws DfException {
    if (activity == null) {
        throw new NullPointerException("activity must be non-null");
    }
        
    // Get the id of the activity
    IDfId activityId = activity.getObjectId();
        
    // Iterate over the activities looking for the specified id.
    // we do this rather than use the value on the activity because that
    // value may not be correct if the name has changed!
    int activityCount = process.getActivityCount();
    for (int i=0; i &lt; activityCount; i++) {
        IDfId id = process.getActivityDefId(i);
        // If the id is found, return the matching name
        if (activityId.equals(id)) {
            return process.getActivityName(i);
        }
    }
       
    // The activity is not used within the specified process. This is an error.
    throw new IllegalArgumentException("dm_activity '" + activityId
                + "' not member of dm_process '" + process.getObjectId() + "'");
}
</code>
            </pre>
<p>This utility method gets the name of &#8220;input port&#8221; for the start activity. In Documentum workflows, ports are logical points of information exchange between activities and must be provided to add a package to a workflow.</p>
<pre>
                <code>
public static String getInputPort(IDfActivity activity) throws DfException {
    for (int i = 0; i &lt; activity.getPortCount(); i++) {
        if (activity.getPortType(i).equals("INPUT")) {
            return activity.getPortName(i);
        }
    }
    return null;
}
</code>
            </pre>
<p>Finally, this utility method gets the name of package for the start activity. This must also be provided to add a package to a workflow.</p>
<pre>
                <code>
public static String getInputPackageName(IDfActivity activity) throws DfException {
    // Iterate over the ports looking for the input port
    for (int i = 0; i &lt; activity.getPortCount(); i++) {
        if (activity.getPortType(i).equals("INPUT")) {
            // Get the name of the package associated with the input port
            return activity.getPackageName(i);
        }
    }
    // If no package is located, return null
    return null;
}
</code>
            </pre>
</li>
</ol>
<h3>
        <a name="head5" class="section">Conclusion</a><br />
    </h3>
<p>We got into the gory details of Documentum workflows and looked at some DQL and DFC code, but the fundamental idea is simple: find any workflows which are in a bad state and restart them. These details are all necessitated by the need to make our system resilient to outages. If you rely on the Java Method Server as we do, hopefully these details will assist you in making your system more resilient too.</p>
<p>While this wouldn&#8217;t be necessary in an ideal world, the reality is that systems with complex integration points can and will have problems. Depending on the criticality of the system, you may want to consider investing in defensive strategies to minimize the impact of these problems.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/automated-workflow-recovery/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Say Scheveningen: A Great New Documentum-Related Blog</title>
		<link>http://www.bluefishgroup.com/2008/great-new-documentum-related-blog/</link>
		<comments>http://www.bluefishgroup.com/2008/great-new-documentum-related-blog/#comments</comments>
		<pubDate>Mon, 24 Nov 2008 04:24:36 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=383</guid>
		<description><![CDATA[I just stumbled across Say Scheveningen, a &#8220;Documentum Technical Tips&#8221; blog by Don Robertson. I&#8217;ve never met Don, but apparently he is the architect for Composer, Documentum&#8217;s tool for configuring all the various components of a Documentum Content Server. Don&#8217;s blog has several posts about aspects and the business objects framework (BOF). The posts look [...]]]></description>
				<content:encoded><![CDATA[<p>I just stumbled across <a href="http://donr7n.wordpress.com/">Say Scheveningen</a>, a &#8220;Documentum Technical Tips&#8221; blog by Don Robertson. I&#8217;ve never met Don, but apparently he is the architect for Composer, Documentum&#8217;s tool for configuring all the various components of a Documentum Content Server. Don&#8217;s blog has several posts about aspects and the business objects framework (BOF). The posts look really good.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/great-new-documentum-related-blog/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Blue Fish Among Fastest Growing Companies in Austin</title>
		<link>http://www.bluefishgroup.com/2008/blue-fish-among-fastest-growing-companies-in-austin/</link>
		<comments>http://www.bluefishgroup.com/2008/blue-fish-among-fastest-growing-companies-in-austin/#comments</comments>
		<pubDate>Sat, 08 Nov 2008 19:43:11 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=382</guid>
		<description><![CDATA[Blue Fish was recently selected as one of the fastest growing companies in one of the fastest growing cities in the country. Each year, the Austin Business Journal identifies the Austin Fast 50 &#8211; the 50 fastest growing companies in town. Blue Fish ranked 10th on their list for 2008. Being selected to the list [...]]]></description>
				<content:encoded><![CDATA[</p>
<p>Blue Fish was recently selected as one of the fastest growing companies in one of the fastest growing cities in the country. Each year, the Austin Business Journal identifies the <i>Austin Fast 50</i> &#8211; the 50 fastest growing companies in town. Blue Fish ranked 10th on their list for 2008.</p>
<p>Being selected to the list is fun, because it shows that even after 9 years, we&#8217;re still making our clients happy and they are giving us more and more projects to work on.</p>
<p>On a related note, I recently returned from a conference of entrepreneurs where I saw some old friends and made several new ones. It was great to hear them talking about all the positive things going on in their companies and how they are still doing well despite the economic downturn. It&#8217;s true that lots of companies are hunkering down for a cold economic winter, but others see the need to control costs as an opportunity.</p>
<p>Here at Blue Fish, many of our clients hire us to help them increase the productivity of their knowledge workers by improving the way they manage and work with content in the enterprise. Our solutions have helped our clients cut costs, improve sales, and reach more customers. This is exactly what companies need to do during tough times, so I don&#8217;t see any reason that we won&#8217;t continue to thrive regardless of the macro economic conditions out there.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/blue-fish-among-fastest-growing-companies-in-austin/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>New Article: Synchronizing Web Content Across Web Publisher Environments</title>
		<link>http://www.bluefishgroup.com/2008/new-article-synchronizing-web-content-across-web-publisher-environments/</link>
		<comments>http://www.bluefishgroup.com/2008/new-article-synchronizing-web-content-across-web-publisher-environments/#comments</comments>
		<pubDate>Sat, 08 Nov 2008 19:16:32 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=380</guid>
		<description><![CDATA[Nicki Dubose and Cory Lowder just released an article about how to keep two Documentum Web Publisher systems synchronized with content and templates. We see a need for this all the time when our clients want to keep their development and test environments up to date with content that&#8217;s been created in their production system, [...]]]></description>
				<content:encoded><![CDATA[<p>Nicki Dubose and Cory Lowder just released an article about how to keep two Documentum Web Publisher systems synchronized with content and templates. We see a need for this all the time when our clients want to keep their development and test environments up to date with content that&#8217;s been created in their production system, or when they want to develop new templates in a development environment, test them in a test environment, and then deploy them to a production environment.</p>
<p>Learn more about it by reading <a href="/library/2008/synchronizing-web-content-across-web-publisher-environments/">Synchronizing Web Content Across Web Publisher Environments</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/new-article-synchronizing-web-content-across-web-publisher-environments/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New Article: Further Streamline BOF Module Deployment During Development</title>
		<link>http://www.bluefishgroup.com/2008/new-article-further-streamline-bof-module-deployment-during-development/</link>
		<comments>http://www.bluefishgroup.com/2008/new-article-further-streamline-bof-module-deployment-during-development/#comments</comments>
		<pubDate>Sat, 08 Nov 2008 19:12:00 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=381</guid>
		<description><![CDATA[Steve McMichael has a new article out explaining how to reduce development time by streamlining the deployment of Documentum BOF components. With Steve&#8217;s creative solution, you can speed up the code-deploy-test cycle time when developing Documentum applications. Read more about how to Further Streamline BOF Module Deployment During Development.]]></description>
				<content:encoded><![CDATA[<p>Steve McMichael has a new article out explaining how to reduce development time by streamlining the deployment of Documentum BOF components. With Steve&#8217;s creative solution, you can speed up the code-deploy-test cycle time when developing Documentum applications.</p>
<p>Read more about how to <a href="/library/2008/further-streamline-bof-deploys/">Further Streamline BOF Module Deployment During Development</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/new-article-further-streamline-bof-module-deployment-during-development/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Synchronizing Web Content Across Web Publisher Environments</title>
		<link>http://www.bluefishgroup.com/2008/synchronizing-web-content-across-web-publisher-environments/</link>
		<comments>http://www.bluefishgroup.com/2008/synchronizing-web-content-across-web-publisher-environments/#comments</comments>
		<pubDate>Fri, 07 Nov 2008 12:00:00 +0000</pubDate>
		<dc:creator>Nicki DuBose</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Web Content Management]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=377</guid>
		<description><![CDATA[Introduction Several of the articles on our website discuss the technical, business-related, and planning challenges inherent in migrating enterprise content from one repository to another. This article focuses on the unique challenges of migrating web content from one Web Publisher environment to another. We&#8217;ll identify the most common web content migration scenarios and discuss options [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Introduction</a><br />
    </h3>
<p>Several of the articles on our website discuss the technical, business-related, and planning challenges inherent in migrating enterprise content from one repository to another.  This article focuses on the unique challenges of migrating web content from one Web Publisher environment to another.  We&#8217;ll identify the most common web content migration scenarios and discuss options for addressing each of them.  We&#8217;ll also explore the elements unique to Web Publisher which must be taken into consideration in a web content migration effort.</p>
<p>Based on client requests and feedback from our peers, we&#8217;ve chosen to address the most common web content migration scenarios:</p>
<ol>
<li>To eliminate the need to re-create the latest content in a test or development environment, migrate web content from one environment to another.</li>
<li>To reduce the risk of testing in a production environment, enable the migration of templates from a development or testing environment into production. </li>
</ol>
<p>What our clients really want is the ability to keep their development, testing, and production environments fresh with the latest and greatest content and templates.  Ideally, our migration approach would allow for low-effort, incremental migrations.</p>
<h3>
        <a name="head2" class="section">Migration Scenarios</a><br />
    </h3>
<p>Most web content migrations fall into one of the following common scenarios:</p>
<h4>Refresh Content</h4>
<p>The most common web content migration request we hear from our clients is to refresh (or synchronize) the content in one environment with that of another.  For instance, since the content in a production environment is frequently updated and maintained, users often request that we migrate that content from production to a development or test environment to facilitate testing with real-world content scenarios.  The reverse is also true.  Content authors might create new content in a development environment while testing a new web site feature.  To avoid having to recreate that content they often request that the content created during development be migrated to production.</p>
<h4>Refresh Templates</h4>
<p>Similar to testing new web site features, developers often make tweaks and changes to templates to support web site changes.  Ideally, developers would make the change in a test environment before putting the change into production.  For most developers, this means a manual effort of exporting templates, presentation files and rules files from a testing environment and then importing them into the production environment.</p>
<h4>Migrate Entire Repository</h4>
<p>Another reason to migrate your content is to upgrade some or all of the software components or hardware platform in your Documentum environment.  You&#8217;ll need a migration plan that allows you to move all of the content and supporting objects and relationships from the source repository to the target.  This scenario is present in all types of content migrations and is not unique to web content, so we will not address it in this article. Look for a future article to address this scenario in greater detail.</p>
<h3>
        <a name="head3" class="section">Web Publisher Migration Challenges</a><br />
    </h3>
<p>There are a number of concepts in Web Publisher that make it different from other Documentum applications.  These concepts add unique challenges to migrating web content, beyond what you might experience in a traditional Documentum migration.  We can group these concepts into three categories: Environmental, Relationships, and Content.</p>
<h4>Environmental</h4>
<p>The following elements are a part of any Documentum repository.  The good news is that all of these environmental artifacts, with the possible exception of Categories, can be migrated using DocApps or DAR files (using Composer).  Optionally, you could also use a third party migration tool to migrate some or all of your environmental artifacts.</p>
<p>Environmental artifacts are generally the same artifacts found in a typical Documentum repository.  These artifacts change infrequently when synchronizing two repositories, so we don&#8217;t necessarily need to concern ourselves with migrating these objects after our initial development or implementation effort.  Below we&#8217;ve identified some of the key environmental artifacts and their role in a Web Publisher environment:</p>
<p>
        <em>XML applications:</em>  One useful feature of Web Publisher is two-way synchronization of properties and content using XML applications.  The XML Application enables automatic population of a piece of content&#8217;s property values when the content file is checked in or imported into Web Publisher.  With two-way population, the opposite is also true.  An author can set property values on a piece of content at the time of creation and the corresponding content values will be updated.</p>
<p>
        <em>Lifecycles:</em>  Web Publisher uses a document lifecycle to define the various states that content will occupy during its life.  In an out-of-the-box Web Publisher environment, content in its draft state is in the Work In Progress (WIP) lifecycle state.  When a piece of content is ready for review and approval it is promoted to the Staging lifecycle state.  After the content is reviewed, it is promoted to the Approved state.  In addition to these standard lifecycle states, many people choose to define custom lifecycles with custom lifecycle states to support their business process.</p>
<p>
        <em>Workflows:</em>  The workflow defines the promotion path, typically from one user or group to another, that the content will take as it passes through the various lifecycle states.   A process workflow will automatically promote a web page to the next state in the lifecycle when certain approval tasks have been completed.</p>
<p>
        <em>Permission Set Templates &amp; User Defined ACLs:</em>  EMC Documentum provides a number of features to manage permissions within Web Publisher.    All Documentum objects are assigned a single Access Control List (ACL).  The ACL assigned to an object sets the access permissions and restrictions for the object.  Permission set templates, which are a special case of ACLs, are applied to a document based on its lifecycle state.  Alias sets can be used as placeholders for user names, group names, and ACL names.  A combination of alias sets and permission set templates set the ACL for web content.  Additionally, some Web Publisher implementations will use custom, user-defined ACLs to set access permissions and restrictions for certain objects as dictated by business processes and security policies.</p>
<p>
        <em>Custom Folders:</em>  In a typical Documentum repository, most folders are of type <code>dm_folder</code>, the standard, out-of-the-box type of folder. But Web Publisher uses a custom type of folder called <code>wcm_channel_fld</code>. When you are migrating documents into a Web Publisher cabinet, you have to make sure that any folders that get automatically created are created as <code>wcm_channel_fld</code> rather than the default <code>dm_folder</code>.</p>
<p>
        <em>Categories:</em>  One of the ways Web Publisher allows users to organize content is via Categories. All Web Publisher solutions will have at least one category instance, the Functional Taxonomy, which organizes content by page type according to the template with which the content was created. Typically, each page type in the system is represented by a category. Categories created to organize content templates by page type are created as functional taxonomy nodes. To associate content to its corresponding category, Web Publisher creates a wcm_category relationship. In essence, the category is another type of folder (a subtype of dm_folder). This type of category is migrated with the corresponding content template in a DocApp or DAR file.</p>
<p>Categories can also be used to define a custom hierarchical taxonomy that can be published to a website as XML. In this case, the root level category is typically a sibling of the functional taxonomy described above. The challenge with this type of category is that it can&#8217;t be migrated using a DocApp or DAR file (using Composer). For this reason, it&#8217;s important that our migration solution support the migration of this special folder sub-type.</p>
<h4>Relationships</h4>
<p>Templates are an integral part of the Web Publisher solution.  Templates enable authors to create and edit content in a familiar form-like interface.  Because templates often drive the content on a web site, it is not uncommon for them to change rather frequently to keep a web site looking fresh and interesting or to incorporate new page features or layouts.</p>
<p>Templates (or document types) are the basis for creating new content in Web Publisher, and are composed of the following set of files:</p>
<ul>
<li>A defining template upon which new files are based</li>
<li>A rules file which defines the fields in the content creation form (optional)</li>
<li>A presentation file which transforms the XML content into a web page  (optional)</li>
<li>A preview/thumbnail file which uses a graphic to identify the templates to content authors  (optional)</li>
</ul>
<p>Web Publisher uses relationships to connect templates to their supporting rules, presentation and preview files.  The image below illustrates the relationships between a sample template and its supporting files:</p>
<div align="center">
        <img src="/article-assets/images/wcm-migrations/sample-template-relationships.png" border="0" alt="Fig. 1: Sample relationships between a template and its supporting objects">
<p class="figure">
            <b><br />
              Figure 1:<br />
            </b> Sample relationships between a template and its supporting objects</p>
</p></div>
<p>To learn more about creating document types, refer to the Web Publisher Developers Guide or the article on this website titled <a href="http://www.bluefishgroup.com/library/2005/web-publisher-template-basics/">&#8220;Web Publisher Template Basics&#8221;</a>
    </p>
<p>Just as the templates have relationships to their supporting files, Web Publisher creates relationships between the content and each of its supporting objects.  The diagram below illustrates some of the common relationships using a sample product page to show the relationships between a piece of web content and its supporting objects.</p>
<div align="center">
        <img src="/article-assets/images/wcm-migrations/sample-content-relationships.png" border="0" alt="Fig. 2: Relationships for Sample Product Page">
<p class="figure">
            <b><br />
              Figure 2:<br />
            </b> Relationships for Sample Product Page</p>
</p></div>
<p>Below is a summary of some of the most important relationships that Web Publisher content might have: </p>
<p>    <well_formed_html></p>
<table>
<thead>
<tr>
<td><em>Relation Name</em></td>
<td><em>Description</em></td>
</tr>
</thead>
<tr>
<td>wcm_category</td>
<td>Tracks the category for an object</td>
</tr>
<tr>
<td>wcm_default_workflow</td>
<td>Tracks the relationship between the template and its default process workflow</td>
</tr>
<tr>
<td>wcm_doc_template</td>
<td>Tracks the template from which the content was created</td>
</tr>
<tr>
<td>wcm_dynamic_content</td>
<td>Indicates content that uses xDQL queries that require transformation</td>
</tr>
<tr>
<td>wcm_editor_link</td>
<td>Tracks other files that are linked to the content file</td>
</tr>
<tr>
<td>wcm_ewebeditpro_link</td>
<td>Tracks other files that are linked to the content file when the content file is modified by eWebEditPro*</td>
</tr>
<tr>
<td>wcm_html_editor</td>
<td>Indicates when a file is editable by eWebEditPro or Rules Editor**</td>
</tr>
<tr>
<td>wcm_layout_template</td>
<td>Tracks the presentation file used to transform the content</td>
</tr>
<tr>
<td>wcm_my_template</td>
<td>Tracks the category for a favorite template</td>
</tr>
<tr>
<td>wcm_native_edit</td>
<td>Tracks the objects that use a local editor</td>
</tr>
<tr>
<td>wcm_process_workflow</td>
<td>Tracks the process workflow attached to content</td>
</tr>
<tr>
<td>wcm_publishing_template</td>
<td>Tracks the publishing template for an object</td>
</tr>
<tr>
<td>wcm_rules_editor</td>
<td>Tracks if content is checked out by the Rules Editor tool</td>
</tr>
<tr>
<td>wcm_rules_template</td>
<td>Tracks the rules file used for content authoring</td>
</tr>
<tr>
<td>wcm_pb_blueprint_template</td>
<td>Tracks the relationship for taxonomy management</td>
</tr>
<tr>
<td>wcm_template_thumbnail</td>
<td>Tracks the thumbnail graphics for the template</td>
</tr>
</table>
<p>
            <sub>*   eWebEditPro is an optional HTML editing tool packaged for use in Web Publisher</sub>
        </p>
<p>
            <sub>** Rules Editor is an optional tool that simplifies creation of rules file XML</sub>
        </p>
<p>    </well_formed_html></p>
<h4>Content</h4>
<p>We mentioned that the template, together with the rules file, enables the content author to enter the content in a standardized form.  The form simplifies adding elements like images and links, and ensures consistency across all pages of a certain type.  Web content created using a template and rules file is stored as XML in Web Publisher.  To maintain the reference between the content and any images or included text files on the page, Web Publisher embeds the document id of the image or text file into the content XML file.</p>
<div align="center">
        <img src="/article-assets/images/wcm-migrations/embedded-ids.png" border="0" alt="Fig. 3: Image IDs embedded in sample content XML">
<p class="figure">
            <b><br />
              Figure 3:<br />
            </b> Image IDs embedded in sample content XML</p>
</p></div>
<p>These embedded object IDs are used within the template to display which object has been selected by the content author when using the out-of-the-box graphic image (or text) selector provided with Web Publisher.</p>
<h3>
        <a name="head4" class="section">Migration Tools and Web Publisher</a><br />
    </h3>
<p>The best way to address the challenges of migrating web content from one Web Publisher environment to another is to use a migration tool that is up to the task. Although we may be a little biased, we think that Migration Workbench is the <a href="/content-migrations/migration-workbench.php">best tool to use for Documentum migrations</a>, and it has several features that were specifically designed to synchronize WCM repositories.</p>
<p>As we stated earlier, one of the main motivators for moving web content from one environment to another is to keep development, testing, and production environments synchronized and fresh with the latest and greatest content and templates regardless of where it was created. This implies an ongoing, or iterative, process rather than the &#8220;one-time push&#8221; that is commonly associated with content migration initiatives. Therefore, you want to select a tool that supports an iterative approach &#8211; meaning you configure the migration process once and run it repeatedly at specified intervals. With each run, any new or updated documents will be migrated to the target system, and any deleted documents will be removed from the target system. Migration Workbench is the only tool we know of that does this.</p>
<p>But supporting an iterative approach is just the first item on the list. For a successful web content migration, the tool you use will also need the following capabilities to address the unique challenges of web content migrations.</p>
<h4>Environmental</h4>
<p>While DocApps and DARs can be used to migrate most of the environmental elements we discussed above, you also need to consider the effect these elements have on content.</p>
<p>For instance, it&#8217;s possible that some of the content in your source repository will be in the middle of a workflow.  Depending on your business requirements, you may want to migrate only the content that has been completed and approved.  If that&#8217;s the case, you&#8217;ll need a migration approach that will allow you exclude certain content from the migration based on some criteria. Migration Workbench uses migration rules to evaluate property values, such as the lifecycle state, to determine which content to migrate.</p>
<p>You may have a business case for migrating content that is in an intermediate lifecycle state &#8211; it&#8217;s neither in its initial lifecycle state nor in its final state.  For instance, you may want to migrate all content &#8211; whether it&#8217;s in WIP, Staging, or Approved.  Intermediate states, such as Staging, are often &#8220;non-attachable&#8221;.  If content is in a non-attachable state, it cannot be imported into the system in that state.  Instead, the content must be imported into the system in an attachable state, such as WIP, and then promoted to the intermediate (or non-attachable) state.  The migration tool should support setting an object to an initial, attachable state, such as WIP, and then auto-promote it to a desired state, such as Staging. This is one of the advanced features of Migration Workbench.</p>
<p>Earlier in this article we discussed how Web Publisher uses a combination of alias sets and permission set templates to set the ACL for the content in a repository. The permission sets and ACLs are generally moved from one repository to another using custom DocApps or DAR files. Your migration tool must allow you to define the rules by which a permission set template was used to attach an ACL to a piece of content in the source system, and then re-apply the correct ACL after the content is imported into the target system. Migration Workbench can determine and attach the correct ACL depending of the lifecycle state or other properties of the document.</p>
<p>Your migration tool must also deal with the fact that Web Publisher uses a custom folder type called <code>wcm_channel_fld</code>. Most migration tools will automatically create folders when neccessary, if the folder does not already exist when trying to link a document into it. But Migration Workbench allows you to specify what type of folder should be created. This ensures that all the folders in your repository will be the right type (<code>wcm_channel_fld</code>) rather than the default.</p>
<p>Finally, since some categories cannot be moved in a DocApp or DAR file, your migration tool must be able to migrate your complete category folder structure prior to migrating the web content into those folders. Migration Workbench can migrate custom folder types such as categories, keeping all the custom attribute values intact.</p>
<h4>Relationships</h4>
<p>Because Web Publisher relys so heavily on relationships to tie together the different components of a web page, the migration tool must be able to migrate these relationships easily.  Recall the diagram of object relationships earlier in this article; each arrow represents one relationship and all of these relationships must be reassembled in the target system for each piece of web content. This means the tool must maintain a source-to-target mapping for the migrated object IDs, migrate the relationship object and then update the parent and child fields with the new IDs that were generated by Web Publisher when the parent and child objects were imported.  Following this sequence is essential.</p>
<p>Other relationships link one migrated object to a non-migrated object, such as workflows which are usually moved from one environment to another using a DocApp or Composer.  In this case, the tool must be able to update the migrated relationship object with the Web Publisher-generated ID for the migrated object and then perform a lookup into the target repository to get the ID of the non-migrated object.</p>
<p>Migration Workbench supports both of these scenarios.</p>
<h4>Content</h4>
<p>To update embedded object IDs, your migration tool should maintain a source-to-target mapping for the object IDs so it can update the IDs embedded in the content XML file with the new ID assigned when the related image or content file was imported. Sequence is important; this step must occur after the related object is imported so the new ID is known. You may also opt to ignore the embedded object IDs.  As long as you migrate both the content and the embedded content into the appropriate folders, you&#8217;ll find that the resulting web page will render appropriately.  If the embedded IDs are not updated in the target content object, then content authors can expect to see errors similar to the one below when editing content.  Reselecting the embedded content and saving will resolve the error.</p>
<pre>
        <code>The previously selected Documentum object 09000405800dc63 is unavailable.  The object is unavailable either because it was not 
found, or you do not have the correct permissions to open the object.  
Select an object and click Save to overwrite the previous selection.  
Otherwise, make no selection and click Save to continue using the same object.</code>
    </pre>
<h3>
        <a name="head5" class="section">Summary</a><br />
    </h3>
<p>Our goal in writing this article was to highlight some of the unique challenges inherent in web content migrations between Web Publisher environments. Hopefully you have gained some insight that will help you anticipate these challenges and plan for them in your next web content migration initiative.</p>
<p>Experience has taught us that selecting the right migration tool is key to addressing the challenges unique to web content migrations.  Ideally, a migration tool will enable everything from simple, iterative migrations of content to entire repository migrations.  Here at Blue Fish, we&#8217;ve been working hard at solutions to overcome these challenges.  Visit our product information page to learn more about how <a href="/content-migrations/migration-workbench.php">Migration Workbench</a> can be a part of your web content migration solution. And for more information on the Blue Fish Agile Migration Methodology, including the concept of an iterative approach which we call incremental migrations, please see the article titled <a href="/library/2008/using-migration-workbench/">&#8220;Using Migration Workbench to Address Common Content Migration Issues&#8221;</a>.</p>
<h3>
        <a name="head6" class="section">Additional Resources</a><br />
    </h3>
<p>For additional information, try the following documentation:</p>
<ul>
<li>Content Server Administration Guide</li>
<li>Web Publisher Administration Guide</li>
<li>Web Publisher Development Guide</li>
<li>Web Publisher User Guide</li>
</ul>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/synchronizing-web-content-across-web-publisher-environments/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Further Streamline BOF Module Deployment During Development</title>
		<link>http://www.bluefishgroup.com/2008/further-streamline-bof-deploys/</link>
		<comments>http://www.bluefishgroup.com/2008/further-streamline-bof-deploys/#comments</comments>
		<pubDate>Fri, 07 Nov 2008 12:00:00 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Custom ECM Solutions]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=379</guid>
		<description><![CDATA[Introduction In a previous article, Automate BOF Module Deployment During Development. I detailed how to install Documentum Business Object Framework (BOF) Modules using an undocumented Ant task provided by Documentum&#8217;s Application Builder. With the BOFPackaging Ant task, it is possible to install and update modules in an automated manner, freeing us from having to maintain [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Introduction</a><br />
    </h3>
<p>
			In a previous article,<br />
			<a href="/library/2008/bof-ant-task/">Automate BOF Module Deployment During Development</a>.<br />
			I detailed how to install Documentum Business Object<br />
			Framework (BOF) Modules using an undocumented Ant task<br />
			provided by Documentum&#8217;s Application Builder. With the<br />
			BOFPackaging Ant task, it is possible to install and update<br />
			modules in an automated manner, freeing us from having to<br />
			maintain these modules manually through docapps during<br />
			development.
		</p>
<p>
			While the automated BOFPackaging task represents a<br />
			significant improvement over manual deployments, it too can<br />
			be inefficient at times. Namely, the BOFPackaging task will<br />
			completely re-install all of a module&#8217;s Java archive (JAR)<br />
			files, including all third party dependencies (e.g., XML<br />
			parsers, Log4j, etc.) which are unlikely to have changed.<br />
			Often these static libraries can total several megabytes in<br />
			size, and the update process will waste several minutes -<br />
			even upwards to an hour over a poor network &#8211; updating them<br />
			unnecessarily. Considering that my fellow developers and I<br />
			will re-deploy a module numerous times during development,<br />
			the time wasted updating library files that haven&#8217;t been<br />
			modified quickly adds up. As such, we&#8217;re discouraged from<br />
			deploying many, small updates which are otherwise more<br />
			efficient and less error-prone, and instead will batch<br />
			enhancements into larger updates that are more difficult to<br />
			isolate, test, and troubleshoot.
		</p>
<p>
			To address this problem, I created a generic, commandline<br />
			application, FileLoader, which can add new files or update existing files in a<br />
			docbase. I use the FileLoader<br />
			tool within my Ant build scripts to update only the JAR<br />
			files that are likely to have changed while developing my<br />
			project&#8217;s modules. In this article, I&#8217;ll describe how my<br />
			FileLoader works and how Documentum makes these efficient<br />
			updates possible.
		</p>
<p>
			For your reference, links to all source code can be found at<br />
			the end of this article.
		</p>
<h3>
        <a name="head2" class="section">Review of BOF Object Schema and Folder Structure</a><br />
    </h3>
<p>
			Before we dive into the implementation of the FileLoader,<br />
			let&#8217;s review the object schema and folder structure of a BOF<br />
			module.
		</p>
<p>
			As of DFC 5.3, Documentum BOF code is stored in the<br />
			repository and dynamically loaded by DFC as needed by client<br />
			application code. Service Based Objects (SBOs) are hosted in<br />
			a single &#8220;global repository&#8221;, providing the same<br />
			functionality to multiple repositories, while Type Based<br />
			Objects (TBOs) are hosted and configured in the repository<br />
			that uses them. Additionally, Documentum introduced the<br />
			concept of a &#8220;simple module&#8221;, which is a unit of executable<br />
			code stored in the repository. Like TBOs, simple modules are<br />
			hosted in the repository that uses them.
		</p>
<p>
			To support this module framework, a few new object types<br />
			were introduced: &#8220;dmc_module&#8221;, &#8220;dmc_jar&#8221;, and &#8220;dmc_java_library&#8221;.<br />
			The &#8220;dmc_module&#8221; type is a subtype of &#8220;dm_folder&#8221; and represents<br />
			a BOF module. A &#8220;dmc_module&#8221; is comprised of the &#8220;dmc_jar&#8221; and<br />
			&#8220;dmc_java_library&#8221; objects that are contained within it.<br />
			(Technically, &#8220;dmc_java_library&#8221; objects are associated with<br />
			&#8220;dmc_module&#8221; objects through dm_relation objects, enabling the<br />
			Java libraries to be reused across modules. But it&#8217;s common<br />
			practice for each module to have its own &#8220;dmc_java_library&#8221;<br />
			object linked directly under it within the repository.) The<br />
			&#8220;dmc_jar&#8221; type is a subtype of dm_document and represents<br />
			individual JAR files. The &#8220;dmc_java_library&#8221; type is another<br />
			subtype of &#8220;dm_folder&#8221; and represents the set of &#8220;dmc_jar&#8221;<br />
			objects that are contained within it. A module will<br />
			typically include a &#8220;dmc_jar&#8221; object for the module&#8217;s<br />
			interfaces, a &#8220;dmc_jar&#8221; object for the implementation of the<br />
			module&#8217;s interfaces, and a single &#8220;dmc_java_library&#8221;<br />
			containing all of the module&#8217;s runtime dependencies.
		</p>
<p>
			Every repository has a System cabinet, which contains a top<br />
			level folder named Modules. By convention, modules are<br />
			installed under this folder according to their type. For<br />
			example, SBOs are installed under &#8220;/System/Modules/SBO&#8221;, and<br />
			TBOs are installed under &#8220;/System/Modules/TBO&#8221;. For simple<br />
			modules, you can reuse existing or create additional<br />
			subfolders of &#8220;/System/Modules&#8221; that match your modules&#8217;<br />
			types. For example, if the repository uses Java-based<br />
			evaluation of validation expressions, the associated modules<br />
			would appear under &#8220;/System/Modules/Validation&#8221;. The hierarchy<br />
			of folders under &#8220;/System/Modules/&#8221; is referred to as the<br />
			repository&#8217;s module registry, or simply its registry.
		</p>
<p>
			The following screenshot is an example of one repository&#8217;s<br />
			module registry as seen through Webtop.
		</p>
<p><div align="center">
            <img src="/article-assets/images/further-streamline-bof-deploys-module-folders.png" border="0" alt="Fig. 1: Figure">
<p class="figure">
                <b><br />
              Figure 1:<br />
            </b> Subfolders of Modules representing BOF types.</p>
</p></div>
</p>
<p>
			Please see the &#8220;BOF Infrastructure&#8221; section of the<br />
			Documentum Foundation Classes Development Guide for a full<br />
			description of BOF Modules.
		</p>
<h3>
        <a name="head3" class="section">Hot Deployments</a><br />
    </h3>
<p>
			When any of a module&#8217;s JAR files are updated in the<br />
			repository, Documentum will automatically update the BOF<br />
			object caches on all client machines to include the updated<br />
			JAR files, and the DFC BOF<br />
			<a target="_blank" href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/ClassLoader.html">ClassLoader</a><br />
			will redeploy the classes loaded within a client<br />
			application&#8217;s JVM without requiring an application restart.
		</p>
<p>
			FThis hot deploy behavior unlocks even more value from the<br />
			FileLoader utility. Using the FileLoader, we can checkin new<br />
			versions of a module&#8217;s JAR files, and all applications<br />
			(e.g., Documentum Administrator, Webtop, Documentum Java<br />
			Method Server, and custom web applications) will immediately<br />
			pick up the new behavior without any interaction required.<br />
			This is a tremendous time saver for developers.
		</p>
<p>
			How does the Business Object Framework know when a module&#8217;s<br />
			JAR files have been updated? In DFC 5.3, they used an early,<br />
			internal version of the Aspects feature that is now publicly<br />
			available starting with the release of Documentum 6.0. By<br />
			inspecting the r_aspect_name repeating attribute on all<br />
			&#8220;dmc_jar&#8221; objects, we see that the Business Object Framework<br />
			attaches a change monitor Aspect<br />
			(&#8220;com.documentum.fc.bof.bootstrap.DfModuleItemChangeMonitor&#8221;)<br />
			to all JAR files loaded into the repository. When a &#8220;dmc_jar&#8221;<br />
			object is updated, the change monitor Aspect is invoked and<br />
			notifies a modification manager<br />
			(&#8220;com.documentum.fc.bof.util.IDfModificationManager&#8221;) of the<br />
			change. The modification manager encapsulates a distributed<br />
			system that ensures all running DFC client applications are<br />
			notified of the change. The BOF ClassLoader within the DFC<br />
			client application will then reloads all classes that<br />
			originated from the modified JAR file, and the client<br />
			application acquires the new behavior.
		</p>
<p>
			I should warn that despite this sophisticated framework,<br />
			client applications may occasionally fail to pick up the<br />
			changes made to a module. When this happens, shut down the<br />
			client application, delete the repository&#8217;s BOF object cache<br />
			on the client machine<br />
			(&#8220;[install drive]:Documentumcache[DFC version]bof[repository name]&#8220;),<br />
			and restart the client application. DFC will then<br />
			refresh the client machine&#8217;s BOF cache upon startup and pick<br />
			up the changes made to the module.
		</p>
<h3>
        <a name="head4" class="section">The FileLoader Commandline Tool</a><br />
    </h3>
<p>
			The FileLoader is a relatively simple commandline tool. You<br />
			can use it to load or update a set of documents in a<br />
			repository. For each file processed, the FileLoader will<br />
			look for a corresponding document in the repository using<br />
			the docbase location provided and the name of the file on<br />
			the client machine to make a call to<br />
			&#8220;IDfSession.getObjectByPath(docbaseFilePath)&#8221;. If the files<br />
			don&#8217;t already exist within the target repository, then new<br />
			documents will be created and linked into the correct<br />
			folder. If the files do exist, then they&#8217;ll be saved, minor<br />
			versioned (default), or major versioned as desired. For new<br />
			documents, it is possible to specify the documents&#8217; object<br />
			type and content type as well.
		</p>
<p>
		    The following table describes the options supported by the FileLoader:</p>
<table>
<table>
<tr>
<td><b>Argument</b></td>
<td><b>Description</b></td>
</tr>
<tr>
<td>&#8211;contentType [arg]</td>
<td>The DFC content type for the file(s). (Optional. Default is &#8216;crtext&#8217;.)</td>
</tr>
<tr>
<td>&#8211;docbase [arg]</td>
<td>The docbase name.</td>
</tr>
<tr>
<td>&#8211;docbaseFolder [arg]</td>
<td>The docbase folder for the file(s).</td>
</tr>
<tr>
<td>&#8211;domain [arg]</td>
<td>The user&#8217;s domain.</td>
</tr>
<tr>
<td>&#8211;objectType [arg]</td>
<td>The DFC object type for the file(s). (Optional. Default is &#8220;dm_document&#8221;.)</td>
</tr>
<tr>
<td>&#8211;password [arg]</td>
<td>The user&#8217;s password.</td>
</tr>
<tr>
<td>&#8211;username [arg]</td>
<td>The user&#8217;s username.</td>
</tr>
<tr>
<td>&#8211;version [arg]</td>
<td>How to version an existing file ['same', 'minor', 'major']. (optional).</td>
</tr>
</table>
</table>
<p>            The files to upload should be passed to the FileLoader as arguments<br />
            after the last commandline option. A sample usage might look like</p>
<pre>
            <code>

C:java .. com.bluefishgroup.util.FileLoader --docbase=db1 --username=steve --password=password --docbaseFolder=/System/Modules/TBO/bf_custom_doc/ C:/dev/build/bf-tbo-int.jar C:/dev/build/bf-tbo-impl.jar

</code>
        </pre>
<p>        Finally, for existing files that should be minor- or major-versioned,<br />
        the FileLoader follows Documentum&#8217;s recommended practice of leveraging<br />
        the IDfCheckoutOperation and IDfCheckinOperation.
        </p>
<p>
            The code sample below represents FileLoader&#8217;s main file processing logic:</p>
<pre>
            <code>

/**
 * Uses loginName to establish a session, creates folders as necessary
 * to build up the path in the docbase, and then uploads each file
 * in the collection.
 */
protected void execute() throws Exception {
    IDfSession session = getSession();

    // First create the folders in the path.
    createFolders();
    
    // Now upload each file, versioning existing content as appropriate
    for (int i=0; i &lt; files.length; i++) {
        // Local file to load.
        File file = createFile(files[i]);
        // Object name.
        String objName = file.getName();
        // Full docbase object path.
        String docbaseFilePath = docbaseFolder + (docbaseFolder.endsWith("/") ? "" : "/") + objName;
        
        System.out.println();
        System.out.println("        File:  " + file.getAbsolutePath());
        System.out.println(" Object name:  " + objName);
        System.out.println("Docbase path:  " + docbaseFilePath);
        System.out.println();

        IDfSysObject doc = (IDfSysObject) session.getObjectByPath(docbaseFilePath);
        if (doc == null) {
            System.out.println("Creating new file in docbase.");
            doc = (IDfSysObject) session.newObject(objectType);
            doc.setObjectName(objName);
            doc.link(docbaseFolder);
            doc.setContentType(contentType);
            doc.setFile(file.getAbsolutePath());
            doc.save();
        } else {
            System.out.println("Updating file in docbase.");
            checkout(session, doc);
            checkin(session, doc, file);
        }
        
        System.out.println("Loaded.");
    }
}

</code>
        </pre>
</p>
<p>
            To use the FileLoader in your Ant scripts, I suggest creating an<br />
            Ant target to encapsulate the java task that will invoke the FileLoader:</p>
<pre>
            <code>

&lt;target name="_run-file-loader" depends="compile" description="Updates files in the docbase."&gt;
	&lt;property name="fileloader.optional.args" value="" /&gt;

	&lt;java classname="com.bluefishgroup.util.FileLoader" fork="true" failonerror="true"&gt;
		&lt;classpath&gt;
			&lt;path refid="project.class.path" /&gt;
		&lt;/classpath&gt;

		&lt;arg line="--docbase=${docbase.name} --username=${docbase.username} --password=${docbase.password}" /&gt;
		&lt;arg value="--docbaseFolder=${fileloader.location}" /&gt;
		&lt;arg value="--version=${fileloader.version}" /&gt;
		&lt;arg line="${fileloader.optional.args}" /&gt;
		&lt;arg line="${fileloader.files}" /&gt;

		&lt;!-- We need the lava.library.path set to pickup the DMCL DLLs --&gt;
		&lt;sysproperty key="java.library.path" value="${documentum.lib.dir}" /&gt;
	&lt;/java&gt;

&lt;/target&gt;

</code>
        </pre>
</p>
<p>
            Then to update TBOs, SBOs, and simple modules, simply call the<br />
            &#8220;_run-file-loader&#8221; target with the correct parameters.
        </p>
<p>
            Here&#8217;s the Ant target included that I&#8217;ve written to update this article&#8217;s sample TBO:</p>
<pre>
            <code>

&lt;target name="update-tbo" depends="init" description="Updates document TBO jar files in the docbase (no 3rd party dependencies)."&gt;
	&lt;antcall target="_run-file-loader" inheritRefs="true"&gt;
		&lt;param name="fileloader.location" value="/System/Modules/TBO/${tbo.module.name}" /&gt;
		&lt;param name="fileloader.version" value="minor" /&gt;
		&lt;param name="fileloader.optional.args" value="--contentType=jar" /&gt;
		&lt;param name="fileloader.files" value="${tbo.int.jar.file} ${tbo.impl.jar.file}" /&gt;
	&lt;/antcall&gt;
&lt;/target&gt;

</code>
        </pre>
</p>
<p>
            Here&#8217;s the Ant target included that I&#8217;ve written to update this article&#8217;s sample SBO:</p>
<pre>
            <code>

&lt;target name="update-sbo" description="Updates SBO jar files in the docbase (no 3rd party dependencies)."&gt;
	&lt;antcall target="_run-file-loader" inheritRefs="true"&gt;
		&lt;param name="fileloader.location" value="/System/Modules/SBO/${sbo.module.name}" /&gt;
		&lt;param name="fileloader.version" value="minor" /&gt;
		&lt;param name="fileloader.optional.args" value="--contentType=jar" /&gt;
		&lt;param name="fileloader.files" value="${sbo.int.jar.file} ${sbo.impl.jar.file}" /&gt;
	&lt;/antcall&gt;
&lt;/target&gt;

</code>
        </pre>
</p>
<p>
            Finally, here&#8217;s the Ant target included that I&#8217;ve written to update this article&#8217;s sample simple module:</p>
<pre>
            <code>

&lt;target name="update-module" description="Updates module jar file in the docbase (no 3rd party dependencies)."&gt;
	&lt;antcall target="_run-file-loader" inheritRefs="true"&gt;
		&lt;param name="fileloader.location" value="/System/Modules/Lifecycle/${lifecycle.module.name}" /&gt;
		&lt;param name="fileloader.version" value="minor" /&gt;
		&lt;param name="fileloader.optional.args" value="--contentType=jar" /&gt;
		&lt;param name="fileloader.files" value="${lifecycle.module.jar.file}" /&gt;
	&lt;/antcall&gt;
&lt;/target&gt;

</code>
        </pre>
</p>
<h3>
        <a name="head5" class="section">Conclusion</a><br />
    </h3>
<p>
		    By taking advantage of the cache update and hot deployment features<br />
		    built into Documentum&#8217;s Business Object Framework, the FileLoader<br />
		    utility can save you valuable minutes each time you update a module<br />
		    by updating only the JAR files that are likely to have changed.<br />
		    These minutes multiplied over the entire development team and length<br />
		    of the release can quickly add up to hours or even days of overall<br />
		    effort. That&#8217;s a significant savings that eliminates most of the<br />
		    tedium from BOF development and can sometimes make the difference<br />
		    between project success and failure.
		</p>
<h3>
        <a name="head6" class="section">Further Reading</a><br />
    </h3>
<ul>
<li>Article source code &#8211; <a href="/article-assets/code/bof_ant_task_samples.zip">bof_ant_task_samples.zip</a>
            </li>
<li>
                <a href="/library/2008/bof-ant-task/">Automate BOF Module Deployment During Development</a>, by Steve McMichael</li>
<li>
                <a href="/library/2006/practical-guide-to-bof/">A Practical Guide to the Business Object Framework</a>, by Jason Duke</li>
<li>Documentum Foundation Classes (DFC) 5.3 Development Guide: Chapter 3 &#8211; Using the Business Object Framework (BOF)</li>
<li>
                <a target="_blank" href="http://ant.apache.org/">Apache Ant</a>
            </li>
</ul>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/further-streamline-bof-deploys/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Case Study: Allowing Geological Passion to be Shared and Interpreted Online—University of Leeds Virtual Seismic Atlas</title>
		<link>http://www.bluefishgroup.com/2008/case-study-allowing-geological-passion-to-be-shared-and-interpreted-online-university-of-leeds-virtual-seismic-atlas/</link>
		<comments>http://www.bluefishgroup.com/2008/case-study-allowing-geological-passion-to-be-shared-and-interpreted-online-university-of-leeds-virtual-seismic-atlas/#comments</comments>
		<pubDate>Thu, 30 Oct 2008 21:47:39 +0000</pubDate>
		<dc:creator>Leighton Hendrick</dc:creator>
				<category><![CDATA[Case Studies]]></category>
		<category><![CDATA[Information Access]]></category>
		<category><![CDATA[information access]]></category>
		<category><![CDATA[University of Leeds]]></category>
		<category><![CDATA[Virtual Seismic Atlas]]></category>

		<guid isPermaLink="false">http://bluefishgroup.wpengine.com/?p=764</guid>
		<description><![CDATA[When a group of university researchers decided to share their amassed geological knowledge online with free access to all interested, they faced a unique challenge. This knowledge was based on seismic images, huge pictures of the Earth&#8217;s crust created using special survey equipment, together with geological interpretation overlain on top. Even if you are an [...]]]></description>
				<content:encoded><![CDATA[<p><a href="http://bluefishgroup.wpengine.com/wp-content/uploads/2013/02/leeds_logo_120.png"><img class="alignleft  wp-image-754" style="margin: 5px 10px;" alt="University of Leeds" src="http://bluefishgroup.wpengine.com/wp-content/uploads/2013/02/leeds_logo_120.png" width="120" height="47" /></a>When a group of university researchers decided to share their amassed geological knowledge online with free access to all interested, they faced a unique challenge. This knowledge was based on seismic images, huge pictures of the Earth&#8217;s crust created using special survey equipment, together with geological interpretation overlain on top. Even if you are an expert, it&#8217;s sometime hard to know what these images are showing – could a particular feature be a submarine fault or part of an ancient submarine canyon? How could researchers address these problems – and share their thoughts on the different interpretations?<br />
<br />
Two geologists at the Universities of Aberdeen and Leeds, Professors Rob Butler and Bill McCaffrey decided to find a solution. The result is the Virtual Seismic Atlas (VSA) &#8211; a web site (www.seismicatlas.org) that allows geologists, be they academic scholars, research groups, students or commercial entities around the globe a chance to observe two and three-dimensional images, and to contribute their own interpretations in a collaborative manner to both grow and refine the collection.<br />
<br />
Ultimately, this will make for better understanding of subsurface geology in a field where data is typically expensive to acquire and process. In addition, collaboration among a worldwide community of users will feed a geological passion that provides a better understanding of Earth&#8217;s surface processes.<br />
<br />
&#8220;There were several motivations in undertaking the project,&#8221; says Butler. &#8220;Prior to the development of this image database, researchers looking for information online would go to Google Images, enter a geological term, and often enough wind up with logos for research groups. Or, worse, they would find an image saying, ‘This is not an example.&#8217; Unless you&#8217;re an expert, you wouldn&#8217;t know if you were getting garbage for results.&#8221;<br />
<br />
The VSA team aimed to make the image hunt easier. &#8220;We want to show spectacular subsurface images and tag them in a way that people can actually find them. So if you want to find examples of a type of particular oil reservoir, you can locate those images with few distractions along the way.&#8221;<br />
<br />
In 2004, when Butler and McCaffrey first began contemplating the undertaking, they happened to be doing some collaborative research with BHP Billiton. Impressed by the system Blue Fish had developed for BHP Billiton, they began working with Blue Fish to develop a similar system. Once again, the solution called for the use of the Documentum Embedded Content Server and Endeca&#8217;s Guided Navigation solution.<br />
<br />
&#8220;Leveraging a past solution for the VSA project was helpful,&#8221; says James Brewer, Information Access Practice Manager for Blue Fish. &#8220;We were able to meet goals faster and save the Virtual Seismic Atlas project money.&#8221;<br />
<br />
&#8220;What we liked about the system was that it helps you discover material you might not be aware existed,&#8221; says Butler. &#8220;This serendipitous approach is something I value highly. It&#8217;s a superb way to find new information,&#8221; says Butler, who likens the process to days when, browsing through hard copy journals, he would stumble upon a helpful article he hadn&#8217;t initially been seeking.<br />
<br />
&#8220;As users check out these images, they can post their thoughts on what they think they see and why,&#8221; says Brewer. &#8220;That feedback will help future users with their research. This is a social network for geologists.&#8221;<br />
<br />
In addition, Butler hopes the VSA site will become a publishing environment for do-it-yourselfers interested in uploading and tagging their own images. &#8220;We want to become an online community like YouTube,&#8221; he says. &#8220;The key goal is that the content will be free and available without restriction.&#8221;<br />
<br />
Inherent to success is appealing to researchers who, in the past, have been fond of hoarding their findings. Butler wants to break through that and knows to do so he must develop an irresistible, dynamic site.<br />
<br />
&#8220;Working with Blue Fish has been very creative and interesting,&#8221; says Butler. &#8220;The neat thing is that the Blue Fish team allows us to develop crazy ideas. That&#8217;s important because we&#8217;re pushing into areas that are new.&#8221;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/case-study-allowing-geological-passion-to-be-shared-and-interpreted-online-university-of-leeds-virtual-seismic-atlas/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New Article: Uncommon Thinking About Common Solutions</title>
		<link>http://www.bluefishgroup.com/2008/new-article-uncommon-thinking-about-common-solutions/</link>
		<comments>http://www.bluefishgroup.com/2008/new-article-uncommon-thinking-about-common-solutions/#comments</comments>
		<pubDate>Mon, 27 Oct 2008 03:48:04 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=373</guid>
		<description><![CDATA[Most companies that implement Documentum have big plans for it. They want to standardize on Documentum in an effort to reduce IT costs by eliminating the proliferation of one-off content management solutions. This story is very familiar by now. Large organizations have standardized on databases, operating systems, ERP systems, programming tools, application servers, middleware &#8211; [...]]]></description>
				<content:encoded><![CDATA[<p><img class="left pad-right pad-bottom bordered" src="/article-assets/images/common-solutions/cmnsol-selectedquadrant.jpg"/></p>
<p>Most companies that implement Documentum have big plans for it. They want to standardize on Documentum in an effort to reduce IT costs by eliminating the proliferation of one-off content management solutions.</p>
<p>This story is very familiar by now. Large organizations have standardized on databases, operating systems, ERP systems, programming tools, application servers, middleware &#8211; the list goes on and on. Standardizing on a common technology stack can keep support and maintenance costs down, and it&#8217;s a cornerstone strategy for CIOs everywhere. </p>
<p>But there are some drawbacks to this strategy. I can&#8217;t think of very many &#8220;one size fits all&#8221; solutions to today&#8217;s trickiest IT problems. Most hard problems have lots of nooks and crannies where unique needs are lurking. These nooks and crannies are the niche markets where specialty providers flourish, and these niche markets tend to be too small for the big guys to worry about. The big guys are great at solving the 80% of the problem that is common to all of their customers, but they struggle to address the 20% that makes each of their customers unique. The real challenge that companies face when standardizing on an enterprise solution is that each division or business unit might have its own 20%, and when you add them all up, you have a lot of needs that don&#8217;t get addressed with the out-of-the-box solution.</p>
<p>Here&#8217;s a case in point. Documentum can be deployed across your entire enterprise. It&#8217;s scalable enough to handle billions of documents. It can be distributed globally in a federated environment with replication across multiple data centers. It&#8217;s got an enormous feature set that&#8217;s been developed over more than 15 years. If you are going to standardize on a single ECM platform, you can&#8217;t do much better than Documentum.</p>
<p>But even Documentum doesn&#8217;t solve every problem out-of-the-box. Take airlines, for example. Documentum out-of-the-box can handle their normal business documents just fine. But airlines also have huge technical manuals called Aircraft Maintenance Manuals. These manuals can have more than 50,000 pages each, and a unique manual is required for each aircraft in the fleet. That adds up to a lot of pages! Because these manuals are so large and complex, they require an army of authors, editors, and reviewers. Add to that the regulated nature of the airline industry, and you&#8217;ll find that creating and managing these huge manuals is one of the biggest content management challenges out there. And Documentum doesn&#8217;t have an out of the box solution that can do it. The airlines have to customize the Documentum platform to meet their needs.</p>
<p>Now don&#8217;t get me wrong &#8211; I don&#8217;t blame EMC. The airline market is too small for EMC to focus exclusively on it. And this is my point. Most companies will have some unique requirements that are really important to them, but not very important to the big IT vendors out there. These companies face a real challenge when trying to deploy an enterprise content management solution. If they think too narrowly, the solution won&#8217;t meet all their needs. But if they think to broadly, they could end up with a customized version of Documentum in each department. And that defeats the purpose of a standard solution.</p>
<p>So what&#8217;s a CIO to do? </p>
<p>Josh McJilton has just published an article that could help. As a consultant and project manager here at Blue Fish, Josh has helped some of our clients address this very issue. He&#8217;s discovered that there are actually different types of &#8220;common IT solution&#8221;, and he&#8217;s created a model to help you determine which one is right for your business. </p>
<p>Read all about it in <a href="http://www.bluefishgroup.com/library/2008/uncommon-thinking-about-common-solutions/">Uncommon Thinking About Common Solutions</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/new-article-uncommon-thinking-about-common-solutions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Uncommon Thinking About Common Solutions</title>
		<link>http://www.bluefishgroup.com/2008/uncommon-thinking-about-common-solutions/</link>
		<comments>http://www.bluefishgroup.com/2008/uncommon-thinking-about-common-solutions/#comments</comments>
		<pubDate>Fri, 24 Oct 2008 11:00:00 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Custom ECM Solutions]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=372</guid>
		<description><![CDATA[Introduction When people talk about common solutions, you probably start thinking about a few specific technologies right away. A few examples of the ones most often thought of are Java, .NET, Oracle and Documentum. While it&#8217;s true these technologies can be used to implement common solutions, it&#8217;s not quite as easy as it sounds. Here [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Introduction</a><br />
    </h3>
<p>When people talk about common solutions, you probably start thinking about a few specific technologies right away. A few examples of the ones most often thought of are Java, .NET, Oracle and Documentum. While it&#8217;s true these technologies can be used to implement common solutions, it&#8217;s not quite as easy as it sounds.</p>
<p>Here at Blue Fish, our experience with clients and our own independent analysis has led to the conclusion that there are at least three different types of common solutions. These types, or approaches to building a common solution, highlight differences in how common solutions are built, deployed and maintained. This article will explain the three different approaches we&#8217;ve identified and present a model we&#8217;ve developed to help you select the right approach for your common solution.</p>
<h3>
        <a name="head2" class="section">Understanding the Different Approaches to Common Solutions</a><br />
    </h3>
<p>The three approaches we&#8217;ve identified are specifically targeted at enterprises with departments, divisions or business units large enough to make their own IT decisions. This generally means they&#8217;re also large enough to create custom solutions to address their specific needs. The goal is to find a common solution across these departments that both meets their unique needs and minimizes development, deployment and support costs.</p>
<p>In this environment, identifying the right approach to a common solution is critical. Implement a common solution that doesn&#8217;t provide the flexibility departments need to support their unique business processes, and they won&#8217;t adopt it. Deliver a common solution that requires significant department specific customization to be useful, and you&#8217;ll end up with a bunch of department specific solutions that don&#8217;t look very common to your support and maintenance teams. These outcomes highlight the need to understand the different approaches to common solutions and the importance of selecting the right one for each enterprise solution.</p>
<p>It&#8217;s important to note that it will very likely make sense to use different approaches for different enterprise solutions. Organizations can successfully implement one approach for their enterprise accounting solution but may need to use a totally different approach to achieve the same success for their enterprise content management system. Since most of the solutions Blue Fish builds for our clients are built on Documentum, I&#8217;ll focus on Documentum based solutions for much of the article. However, the reality that there are different approaches to a common solution and the model we present for selecting the right one applies to many other technologies and solution domains.</p>
<p>So, let&#8217;s dive right in and talk through the three different approaches.</p>
<h4>The Configurable Solution Approach</h4>
<p>The &#8216;Configurable Solution&#8217; approach is what most people think of when picturing a common solution. It&#8217;s the archetypal common solution because technically it is the same solution for everyone. This approach gives everyone the exact same technology solution, but then presents a few, well defined configuration points that enable departments or users to tailor it to their needs. All requests for new or modified functionality are reviewed, consolidated and implemented by a central group that owns the solution.</p>
<p>
        <well_formed_html><br />
            <img alt="A Configurable Solution" src="/article-assets/images/common-solutions/cmnsol-wordicon.jpg" style="float: left;margin-top: 10px; margin-right: 20px;margin-bottom: 10px;"></well_formed_html>One great example of a configurable solution is Microsoft Word. It&#8217;s the same technology solution installed the same way throughout your organization. However, each department or individual user can configure Word to best suit their needs. For example, departments can create their own templates and macros to support their business processes. Individual users can organize the toolbars and configure the interface to help make them more productive. In our example, the central group that owns this solution is Microsoft. If you need new functionality that Word doesn&#8217;t provide, you can&#8217;t just go change the code yourself. You have to find a way to get that need on Microsoft&#8217;s radar and hope that it makes it into the next version.</p>
<p>Similar to Microsoft Word, Documentum can be deployed as a configurable solution. Out of the box, Documentum comes with all the features necessary for a basic content management system. You could use the default object types and configure your users, groups, roles and security using the out of box capabilities, and be up and running with no customization whatsoever. However, we&#8217;ve never seen Documentum deployed that way. Here at Blue Fish, we&#8217;ve been helping clients deploy and integrate Documentum for over nine years, and have never deployed it completely out of the box. That said, with each release Documentum moves closer to a completely configurable solution. For example, Documentum 6 added several new configuration points for scoping what menus, templates and other object types are visible to a particular user. This was a common type of customization in the past. Some day, Documentum may achieve the goal of providing a completely configurable solution, but for now some level of customization is almost always required.</p>
<h4>The Customizable Platform Approach</h4>
<p>The &#8216;Customizable Platform&#8217; approach is the default way most organizations build common solutions. This approach leverages a core of commonality to build a starter kit of sorts. With this approach, the common solution isn&#8217;t complete by itself, but rather provides departments with the &#8220;80% solution&#8221; they can use to build the solution they need. A central team owns and maintains the core platform, and each department is free to customize this platform as they see fit. The central group isn&#8217;t necessarily involved, or even aware of the department specific customizations.</p>
<p>
        <well_formed_html><br />
            <img alt="A Customizable Platform" src="/article-assets/images/common-solutions/cmnsol-linuxicons.jpg" style="float: right;margin-top: 10px; margin-left: 15px;"></well_formed_html>My favorite example of a customizable platform is the Linux kernel. There are many different distributions of Linux. A few examples of the more common distributions are Red Hat, SUSE, Fedora, Debian and Ubuntu. At their core, all these distributions share the same code. This core, officially known as the kernel, serves as a common starting point for every distribution of Linux. Each distribution is empowered to modify, extend and even customize the kernel as they see fit to package the solution that fits their needs. In this example, one guy from Finland, Linus Torvalds, owns the core platform and each distribution owner (e.g., Red Hat, SUSE, Ubuntu, etc.) is responsible for building and supporting their customized solution.</p>
<p>Just like Linux, Documentum can be deployed as a customizable platform. EMC expects their customers to extend and customize Documentum, which is why they invest so much in developer tools like WDK and DFS. EMC understands that Documentum can rarely be deployed with configuration alone. The vast majority of Documentum customers use it as a customizable platform by customizing core functionality such as the user interface. Unfortunately, in large enterprises you often find individual departments customizing the platform to meet their specific needs. Over time, the department specific customizations grow further and further apart, and the enterprise ends up with multiple individual solutions that, although they share a common platform, don&#8217;t look so common to your support and maintenance teams. This is how many efforts to implement a common enterprise content management system fail. A company buys Documentum thinking it will be common in the way Microsoft Word is common, and they don&#8217;t plan for the necessary level of development and support.</p>
<h4>The Extensible Framework Approach</h4>
<p>The &#8216;Extensible Framework&#8217; approach provides a set of components and tools that enable departments to assemble focused, complete solutions that meet their unique needs. This approach leverages techniques from both the &#8216;Customizable Solution&#8217; and &#8216;Configurable Platform&#8217; approaches to provide users with the ability to assemble exactly what they need, but prevents the expense of divergent solutions by enforcing standards. The standards define basic rules for assembling a solution, documentation for how components interact with the core framework and the specification that new components must align to in order to operate with the framework. Using this approach, departments assemble exactly what they need from an existing set of components. If the functionality they need is not provided by an existing component, they can use the provided specification to create a new component to plug into the framework.</p>
<p>
        <well_formed_html><br />
            <img alt="An Extensible Framework" src="/article-assets/images/common-solutions/cmnsol-firefox.jpg" style="float: left;margin-left: 10px; margin-top: 10px; margin-right: 20px;"></well_formed_html>A great example of an extensible framework is the Firefox Web Browser. Firefox provides a core solution for browsing the Web. However, if you need to extend the functionality of Firefox to provide custom functionality, you can create your own extension, or &#8216;plug-in&#8217;, to the core solution. There is no need to create a completely custom build of the browser, you simply implement the &#8216;plug-in&#8217; according to the Firefox extension framework standards, and then plug it into the core solution. You can continue to get the value of new releases of the underlying platform without the pain of constantly rebuilding and retesting your &#8216;plug-in&#8217; because it is insulated from platform changes through the extension framework. In our example, the extensible framework solution (i.e., Firefox) is owned by the Mozilla Foundation. All changes to the Firefox itself are managed by Mozilla. Any custom functionality implemented through &#8216;plug-ins&#8217; is managed by the individual or business who originally implemented the &#8216;plug-in&#8217;.</p>
<p>Similar to Firefox, many components of the Documentum platform can be deployed as an extensible framework. Documentum components such as lifecycles, workflows and the Business Object Framework (BOF) provide the ability to extend the core platform without creating custom builds. However, it&#8217;s important to note that the entire Documentum platform cannot be directly deployed as an extensible framework. Many components, such as the user interface, do require the creation of customized builds in order to deploy changes. This doesn&#8217;t mean Documentum can&#8217;t be deployed as a 100% extensible framework; it means that you must invest in design and development to create your own extensible framework for the components that typically require customization. Once you decide to do this, you can build an extensible framework that will enforce enough consistency across solutions to drive down support costs. Because this solution approach will provide extension points that enable departments to build their own components, each department can construct a solution that meets their needs. For example, you could construct a configuration driven, rules-based Documentum framework that uses services to perform tasks such as document numbering, document filing, lifecycle event management and security definition. These core services are shared and any department can plug them in to their solution if they meet the department&#8217;s needs. However, if a department needs to number their documents according to a different standard they can implement their own document numbering extension, and plug it in to their solution. The custom extension can then be shared with other departments who may have similar requirements. Because the new extension aligns to the extension framework standards, other departments will be able to plug it into their solutions in a predictable, repeatable way.</p>
<h4>Comparing the Approaches</h4>
<p>Now that we understand the three models, there is one more important concept to discuss: governance. Applying the appropriate governance model is critical for driving value out of a common solution and governance boils down to one key thing. The way you manage and support differences, or business process exceptions, within your solution is the most important aspect of governing a common solution. We&#8217;ll discuss governance in more detail in the next section. For now, the following table sums up the three solution approaches we&#8217;ve discussed so far, and provides some initial insight into the characteristics of an effective governance model for each approach.</p>
<p>    <well_formed_html></p>
<table>
<thead>
<tr>
<td></td>
<td>Configurable Solution</td>
<td>Customizable Platform</td>
<td>Extensible Framework</td>
</tr>
</thead>
<tbody>
<tr>
<td>Characteristics:</td>
<td>
<ul>
<li>Single build to support</li>
<li>Strong, responsive governance model</li>
<li>Centrally defined configurations exposed to all users</li>
<li>No deployment specific customization</li>
</ul>
</td>
<td>
<ul>
<li>Multiple builds to support</li>
<li>Little governance required</li>
<li>Loosely controlled, deployment specific customizations</li>
<li>Non-standard, diverging customizations drive high support costs</li>
</ul>
</td>
<td>
<ul>
<li>Single build of core framework to support</li>
<li>Strong governance of core framework</li>
<li>Standards-based extension framework</li>
<li>Deployment specific extensions isolated and shared through plug-in model</li>
</ul>
</td>
</tr>
<tr>
<td>Governance:</td>
<td>Strong, responsive governance model consolidates and incorporates all exceptions into centrally managed solution</td>
<td>Minimal centralized governance allows owners of each deployment to deal with exceptions as they see fit</td>
<td>Strong governance for core framework; &#8216;plug-in&#8217; governance distributed to individual departments</td>
</tr>
<tr>
<td>Example:</td>
<td>Microsoft Word</td>
<td>Linux Kernel</td>
<td>Firefox Web Browser</td>
</tr>
</tbody>
</table>
<p>    </well_formed_html></p>
<h3>
        <a name="head3" class="section">Selecting the Best Approach for Your Organization</a><br />
    </h3>
<p>Understanding the different approaches is half the battle. Unfortunately, it&#8217;s the easy half. Identifying and successfully implementing the most appropriate approach for your situation is the real challenge. Do this well and you can drive down solution development and support costs while protecting, and even enhancing, the competitive advantages built into your business processes.</p>
<p>So how is the savvy CIO supposed to select the appropriate approach that fits his/her unique business? Our experience tells us that it mostly boils down to solution governance. But governance doesn&#8217;t just mean locking down the system and forcing all changes through an authoritarian change control process. As the table above hinted at, there are different ways to govern your solution. The key thing to understand is that no single governance approach is always right or always wrong. Depending on your organization&#8217;s size and governance capabilities, one may be more appropriate than another and ultimately this should impact the solution approach you select.</p>
<h4>A Governance Based Selection Model</h4>
<p>Below, Figure 1 depicts a model we&#8217;ve developed for helping select the right approach to your common solution. The model measures the amount of business process commonality in the departments that will use the solution on the X-axis, and the number of times the solution will be implemented (i.e., instances of the solution) on the Y-axis. This is not a quantitative model. There is no discrete amount of commonality or number of instances that should move every business from one approach to another. A thoughtful analysis of your business and an understanding of your roadmap for the future can&#8217;t be replaced by any model. However, this model will help you think about the most important drivers for selecting the right approach to your common solution.</p>
<div align="center">
        <img src="/article-assets/images/common-solutions/cmnsol-selectionquadrants.jpg" border="0" alt="Fig. 1: Solution Approach Selection Model">
<p class="figure">
            <b><br />
              Figure 1:<br />
            </b> Our selection model leverages a governance-based approach to analyze the number of solution instances within your organization and the amount of business process commonality across those solutions.</p>
</p></div>
<p>We view this model as governance-based because measuring the amount of business process commonality is another way to look at the number of exceptions to that commonality that are present in your business; the more commonality, the fewer exceptions and vice versa.</p>
<h4>Managing Exceptions</h4>
<p>I introduced the concept of exceptions in the table that summarized the three approaches to common solutions. Let&#8217;s define exactly what an exception is so that we can discuss their importance in selecting the right approach for a common solution.</p>
<p>Exceptions are essentially the inverse of business process commonality. Let&#8217;s use the business process of creating, reviewing and approving purchase orders to identify a specific example. Assume that your hard working team of analysts has defined a standard purchase order process to be used across your enterprise. However, one business unit isn&#8217;t able to implement that process exactly because of a specific requirement with a key supplier. They can use the majority of the process as-is, but must make one key change to support integration with their primary supplier. This change to the standard purchase order process is an exception.</p>
<p>A typical goal of business process standardization is the identification and elimination of exceptions. For some common solutions, such as your accounting system, word processing technology or desktop operating system, this is an achievable goal. However, other common solutions, such as Content Management systems, are more likely to contain exceptions that business units will want to be supported. Regardless of the specific solution, new exceptions will be discovered throughout the lifecycle of the solution. New business units with new requirements will come online and adopt the solution; your business processes will evolve to adapt to a changing market; there will always be new exceptions, and therefore it is critical that you have a plan for managing them.</p>
<p>The process used to identify, evaluate and ultimately decided how, if at all, to support exceptions is one of the most important aspects of successful solution governance. As we discussed when describing the different approaches to common solutions, each approach requires a unique governance model.</p>
<p>Let&#8217;s look at each approach individually. As we discussed earlier, the &#8216;Configurable Solution&#8217; approach typically requires high business process commonality across your organization. This is because the &#8216;Configurable Solution&#8217; approach generally supports the least number of process exceptions. The governance required to support this type of solution must be centralized and empowered to challenge the nature and value of exceptions that are brought forward for implementation. Otherwise the central team will be swamped with changes and the &#8216;Configurable Solution&#8217; will quickly suffer from feature bloat.</p>
<p>On the other hand, the &#8216;Extensible Framework&#8217; approach requires this strong, centralized governance only for the core framework and the standards that define how components interact with that framework. This core framework and set of standards will change far less often than a complete, configurable solution. By distributing the capability to extend the core framework through well defined components, the central team significantly lightens the load on their governance responsibilities.</p>
<p>Similarly, the &#8216;Customizable Platform&#8217; approach requires relatively little governance compared to the &#8216;Configurable Solution&#8217;. Exceptions are directly built into the individual department solutions through their own customizations. The central group that owns the core platform is responsible for making changes and extending that platform. Because each department is free to customize their own solutions as they see fit, the departments aren&#8217;t required to go through a formal governance process to implement the features they need.</p>
<h4>A Detailed Example</h4>
<p>Let&#8217;s use an example company, Acme Inc., to look at how this selection model is applied.</p>
<p>Acme, Inc. is a large, distributed enterprise with many divisions and departments that require content management. Acme is looking for a way to meet the diverse needs of its business units at the lowest total cost. Acme has selected Documentum as their common technology for content management and now needs to decide how to roll it out to the many divisions and departments across their enterprise.</p>
<p>Acme&#8217;s CIO has decided that initially, this common content management solution will only be used to store and manage business critical documents required to support regulatory compliance. Additionally, all implementations of the common solution will standardize on Documentum&#8217;s Web-based interface to minimize differences in the way users access and interact with the solution. This is beginning to sound like a relatively standardized solution, right? Might be a great candidate for the &#8216;Configurable Solution&#8217; approach you say? Not so fast! Let&#8217;s take a closer look.</p>
<p>As we&#8217;ve said, Acme is a large, global enterprise. They&#8217;ve grown to their present size through a series of strategic acquisitions over the course of several decades. While there are only a few distinct lines of business across the organization, the business units within each of these business lines are scattered across every region of the globe. Further, each of these business units have their own unique history and, to a certain extent, culture. The business units themselves are also generally large enough to make their own IT decisions and implement their own custom solutions. There appears to be a great opportunity to drive standards and reduce costs through a common solution.</p>
<p>Using the selection model presented in this article, Acme creates an initiative to analyze the two key dimensions of the model:<well_formed_html></p>
<ol>
<li>The number of business units, departments and divisions that will implement the common content management system</li>
<li>The amount of commonality in the business processes used to support the generation and management of regulatory compliance documents</li>
</ol>
<p>        </well_formed_html>
    </p>
<p>The number of implementations is relatively easy to determine. Acme has 50 business units around the globe with as many as 10 different departments within each business unit. Ultimately, there will be several hundred unique departments using the common solution.</p>
<p>The amount of business process commonality is more difficult to measure precisely. However, Acme realizes that there are significant differences in the regulations and compliance laws across the many regions where their business units operate. While the basic process of generating and managing compliance documents can be abstracted to look common, the details are often different enough that many, legally-required exceptions begin to materialize.</p>
<p>
        <well_formed_html><br />
            <img alt="Governance Based Selection Model" src="/article-assets/images/common-solutions/cmnsol-selectedquadrant.jpg" style="float: right;margin-top: 10px; margin-left: 15px;"></well_formed_html>Using the governance based selection model, Acme determines that they are in the upper quadrants based on the number of departments they anticipate using the solution. Based on the number of exceptions initially identified they decide that they actually have relatively low commonality across their compliance document management business processes and plot themselves into the &#8216;Extensible Framework&#8217; quadrant.</p>
<p>How do we know Acme arrived at the right answer for their common solution? What does Acme need to do to make sure their investment in a common, extensible framework has a positive impact on the overall business?</p>
<p>If Acme had not used the selection model and simply decided to use the &#8216;Customizable Platform&#8217; approach they would have quickly experienced a maintenance and support nightmare. By building only the customizable platform of the content management system, each individual business unit or department would then be responsible for customizing that platform to address their specific requirements. With several hundred departments to come online, the core platform support organization would eventually have to worry about several hundred unique solutions each time an update to the core was ready to be released. This situation would almost certainly overshadow any benefits gained from sharing a common core platform. For this reason, the selection model only recommends the &#8216;Customizable Platform&#8217; approach when the total number of instances, or implementations, is manageably low.</p>
<p>Had Acme decided that they could manage the regulatory difference across the regions, they could have selected the &#8216;Configurable Solution&#8217; approach. However, this would require that a central team identify and drive out enough exceptions to achieve a high level commonality in their compliance document management business processes. For Acme, achieving that level of commonality may not have even been possible as many of the process differences are driven by regulatory statues that are non-negotiable. Additionally, because the &#8216;Configurable Solution&#8217; approach requires a central team to manage the initial implementation and all subsequent changes, all the process variations would have to be identified and implemented as configuration points by the central team. The team will certainly miss a few necessary configuration points with the first release. Additionally, some of the configurations will almost certainly need to be refined or corrected. Every department will have to wait in line for the central team to address their specific need before they can use the solution. Depending on the capacity of the central team, the departments could end up waiting so long that they give up and implement a custom solution themselves. The entire strategy of a common solution is lost once departments abandon the common solution in favor of their own custom solution.</p>
<p>By selecting the &#8216;Extensible Framework&#8217; approach to their common solution, Acme has positioned their common solution for success by defending against two threats:<well_formed_html></p>
<ol>
<li>Mass solution proliferation of customized versions of a common platform</li>
<li>Low adoption of a configurable solution delivered by a capacity constrained central team</li>
</ol>
<p>        </well_formed_html>To be successful with their extensible framework, Acme must understand and plan for the up-front development investment that is required and must implement an effective governance process. The up-front development will focus on building the core framework and the interface between it and extensions developed by business units and departments. The governance model must ensure that the core framework is not customized when deployed and that extensions align with the standards and are shared across implementations.</p>
<h3>
        <a name="head4" class="section">Summary</a><br />
    </h3>
<p>If you take nothing else away from this article, remember that there are different types of common solutions. Whether it&#8217;s the &#8216;Configurable Solution&#8217;, &#8216;Customizable Platform&#8217; or the &#8216;Extensible Framework&#8217; approach, selecting the right type of common solution is a critical first step on the road to a successful implementation. From there it&#8217;s on to the fun part; designing and building the common solution that fits your organization like a glove.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/uncommon-thinking-about-common-solutions/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>New Article: Introduction to Documentum Composer</title>
		<link>http://www.bluefishgroup.com/2008/new-article-introduction-to-documentum-composer/</link>
		<comments>http://www.bluefishgroup.com/2008/new-article-introduction-to-documentum-composer/#comments</comments>
		<pubDate>Fri, 10 Oct 2008 23:32:17 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=371</guid>
		<description><![CDATA[Jason Duke, a Technical Lead in our Custom ECM Solutions practice, has written an overview of Documentum Composer, EMC&#8217;s latest toolset for creating and deploying Documentum configurations and and other application components. Learn what Jason thinks by reading Introduction to Documentum Composer.]]></description>
				<content:encoded><![CDATA[<p><img class="right pad-left pad-bottom bordered" src="/images/blog/composer-thumb.jpg" height="193" width="300"/></p>
<p>Jason Duke, a Technical Lead in our Custom ECM Solutions practice, has written an overview of Documentum Composer, EMC&#8217;s latest toolset for creating and deploying Documentum configurations and and other application components. </p>
<p>Learn what Jason thinks by reading <a href="http://www.bluefishgroup.com/library/2008/an-introduction-to-documentum-composer/">Introduction to Documentum Composer</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/new-article-introduction-to-documentum-composer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New Article: Creating a Photo Library Using Web Publisher Categories</title>
		<link>http://www.bluefishgroup.com/2008/new-article-creating-a-photo-library-using-web-publisher-categories/</link>
		<comments>http://www.bluefishgroup.com/2008/new-article-creating-a-photo-library-using-web-publisher-categories/#comments</comments>
		<pubDate>Fri, 10 Oct 2008 23:21:53 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=369</guid>
		<description><![CDATA[Marc Perlman just published a new case study / how to article about a project we recently completed for Rio Tinto Minerals. Our client wanted their intranet (manged by Documentum Web Publisher) to contain a Photo Library where users could find approved corporate photos to use in presentations, reports, and other documents. Marc and team [...]]]></description>
				<content:encoded><![CDATA[<p><img class="left pad-right pad-bottom bordered" src="/images/blog/rtm-photo-library-thumb.jpg" height="181" width="300"/></p>
<p>Marc Perlman just published a new case study / how to article about a project we recently completed for Rio Tinto Minerals. Our client wanted their intranet (manged by Documentum Web Publisher) to contain a Photo Library where users could find approved corporate photos to use in presentations, reports, and other documents.  Marc and team created a solution that makes it easy for a user on the intranet to find and preview images before they download them. Marc&#8217;s solution uses Web Publisher&#8217;s categories (think taxonomies) so that photos can be easily tagged against multiple hierarhical keywords.</p>
<p>To learn more, read <a href="http://www.bluefishgroup.com/library/2008/creating-a-photo-library-using-web-publisher-categories/">Creating A Photo Library Using Web Publisher Categories</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/new-article-creating-a-photo-library-using-web-publisher-categories/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>New Article: Challenges Internationalizing Endeca Applications</title>
		<link>http://www.bluefishgroup.com/2008/new-article-challenges-internationalizing-endeca-applications/</link>
		<comments>http://www.bluefishgroup.com/2008/new-article-challenges-internationalizing-endeca-applications/#comments</comments>
		<pubDate>Fri, 10 Oct 2008 23:02:10 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=370</guid>
		<description><![CDATA[Dan Burton, one of our Solution Architects, just wrote an article that discusses some of the challenges we have faced when trying to translate, internationalize, and localize applications built on the Endeca platform. Not only must you worry about translating the user interface components, but you have to plan for how to store the data [...]]]></description>
				<content:encoded><![CDATA[<p><img class="right pad-left pad-bottom bordered" src="/images/blog/endeca-dimension-values-thumb.jpg" height="164" width="300"/></p>
<p>Dan Burton, one of our Solution Architects, just wrote an article that discusses some of the challenges we have faced when trying to translate, internationalize, and localize applications built on the Endeca platform. Not only must you worry about translating the user interface components, but you have to plan for how to store the data and filter out results that are in languages your users don&#8217;t understand. There are some great lessons learned in this article.</p>
<p>Dan has all the details in <a href="http://www.bluefishgroup.com/library/2008/endeca-i18n/">Challenges Internationalizing Endeca Applications</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/new-article-challenges-internationalizing-endeca-applications/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Challenges Internationalizing Endeca Applications</title>
		<link>http://www.bluefishgroup.com/2008/endeca-i18n/</link>
		<comments>http://www.bluefishgroup.com/2008/endeca-i18n/#comments</comments>
		<pubDate>Fri, 10 Oct 2008 11:00:00 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Information Access]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=366</guid>
		<description><![CDATA[Introduction As more and more applications reach out to a global audience, internationalization is becoming an increasingly important aspect of these applications. Since Endeca applications are focused on Information Access, considerations about internationalization are often critical success factors for these globally targeted applications. This article discusses a few of the challenges surrounding building effective internationalized [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Introduction</a><br />
    </h3>
<p>As more and more applications reach out to a global audience, internationalization is becoming an increasingly important aspect of these applications.  Since Endeca applications are focused on Information Access, considerations about internationalization are often critical success factors for these globally targeted applications.  This article discusses a few of the challenges surrounding building effective internationalized applications on the Endeca platform, and a few approaches to tackling those challenges.</p>
<p>In general there are two primary areas in an application where internationalization becomes an important consideration:  the underlying data and the user interface.  Endeca&#8217;s own documentation does a good job of discussing best practices for handling data in multiple languages in Endeca&#8217;s forge process (see the Chapter entitled &#8220;Using Internationalized Data&#8221; in the Endeca IAP Developer&#8217;s Guide).  As such, I&#8217;m going to focus more in this article on some of the challenges in working with the Endeca pipeline configuration and application user interface.</p>
<h3>
        <a name="head1" class="section">Interface Languages, Record Languages, &amp; Interest Languages</a><br />
    </h3>
<p>Imagine an Endeca-powered web application that allows users to search for documents in a company knowledge base.  Since company&#8217;s customers are all over the world, the application is translated into several languages.  The most popular documents within the knowledge base are translated into multiple languages as well. The application gives the user the option to select which languages they can read, so that any documents not written in those languages are filtered out when the user searches the knowledge base.</p>
<p>There are several different ways that languages play an important part in this example.  One of the important distinctions that needs to be made in any internationalized application is the difference between <i>interface languages</i>, <i>record languages</i>, and <i>interest languages</i>.</p>
<p>The <b>interface language</b> is the language that a particular user chooses to use when they are using the application.  All the text controls and labels in the application should be translated into this language when displayed to the user.  For instance, if a user selects &#8220;fran&ccedil;ais&#8221; as their interface language, they might see a button labeled &#8220;Param&egrave;tres&#8221; instead of &#8220;Settings&#8221;.</p>
<p>The <b>record language</b> is the language describing a particular record or document.  Most often this is the language a particular document or record is written in. Usually there is just one record language per record, but sometimes there can be several.  For instance, a single User&#8217;s Guide document might contain sections written in different languages that contain the same basic material.</p>
<p>The <b>interest languages</b> are the languages that a user selects when using the application that dictate which content is shown to that user.  Some applications tie this to the interface language, but that may not be appropriate for all applications.  Users may be interested in content in multiple languages even though they must necessarily choose a single interface language.  In the example above, not all documents are translated into all languages, so some content may only be available in the default language.  Additionally, it may be valuable for application administrators to have access to records across all languages available in the system.</p>
<p>For the various representations of languages in an application, it is highly recommended to use ISO standard language codes.  This will make the language determination clear and consistent.  For the majority of cases, the familiar 2-letter ISO 639-2 codes<well_formed_html><br />
            <sup><a href="#references" name="footnote_1">1</a></sup><br />
        </well_formed_html> are sufficient.</p>
<h3>
        <a name="head1" class="section">Properties &amp; Dimensions</a><br />
    </h3>
<p>When dealing with an internationalized application, there are a couple different ways that you can structure your properties and dimensions.  In all cases, the goal is to provide the user with dimension values in their selected interface language.  For these examples, consider a dimension that describes geographical information called &#8220;Geography&#8221;.  We&#8217;ll just define the first level of hierarchy to keep things simple.</p>
<h4>Dimensions with Resource Key Values?</h4>
<p>User interface frameworks that provide support for internationalization generally have the concept of a resource key.  The resource key is a string that is used to look up (generally from resource bundles) the string to display to a user.  For example, the resource key might be &#8220;n_america&#8221;, which would provide the string &#8220;North America&#8221;, or &#8220;Am&eacute;rique du Nord&#8221;, or &#8220;Nordamerika&#8221; back to the application to display depending on whether the user&#8217;s interface language is set to English, French, or German, respectively.</p>
<p>However, when localizing an Endeca-powered application, it&#8217;s not so straightforward.  Let&#8217;s examine how we could naively approach rendering our Endeca dimensions using resource bundles.  In this approach we make each value of the dimension a resource key, and then use that resource key to look up the appropriate string to display to the user for that dimension value at render time.  This is shown in the Developer Studio screenshot below.</p>
<div align="center">
        <img src="/article-assets/images/endeca_i18n/Figure1.png" border="0" alt="Fig. 1: Using Resource Keys as Dimension Values">
<p class="figure">
            <b><br />
              Figure 1:<br />
            </b> Using Resource Keys as Dimension Values</p>
</p></div>
<p>This has the advantage of keeping your dimension configuration simple and straightforward.  It also means that the only place you need to maintain translations for the dimension values is in resource bundles handled by the user interface.</p>
<p>However, this approach has several shortcomings as well.  First it means that the data in your records has to be tagged using the resource key value only, rather than the various translations of a value.  This may or may not be problematic, depending on how your data is set up.  (You could set up synonyms for each dimension value for each language to get around this, but it rather defeats the point of keeping your dimension configuration simple and isolating the translations in resource bundles.)  </p>
<p>It also means that you can&#8217;t effectively use dimension search with this approach.  Since the dimension values are actually the resource keys (which are never displayed directly to the user) the user can&#8217;t search using the translated values, which only exist in resource bundles handled by the user interface framework and are not available to the Endeca engine.</p>
<p>Another minor drawback is that the display order for Alpha-sort dimensions may appear jumbled, since the alphabetic sort order for the resource keys won&#8217;t always match the sort order of the translations into a given language.  This can be dealt with in the user interface code by having it re-sort the values appropriately after they are translated, but it is additional work that you may want to avoid.</p>
<h4>Dimensions per Language</h4>
<p>A more complex, but more complete approach is to instead create, for each intended dimension, a separate dimension for each available interface language.  Suppose our application will support English, French, Spanish, and German as interface languages.  In that case, the configuration would look something like the following screenshots.</p>
<div align="center">
        <img src="/article-assets/images/endeca_i18n/Figure2.png" border="0" alt="Fig. 2: Defining Dimensions per Language">
<p class="figure">
            <b><br />
              Figure 2:<br />
            </b> Defining Dimensions per Language</p>
</p></div>
<p>Prefixing each dimension with its 2-letter language code makes them easy to identify.  Notice also that I have selected &#8220;French&#8221; as the dimension language.  Selecting &#8220;French&#8221; as the dimension language tells Endeca to treat values in this dimension as French words, which helps dimension searches against this dimension be more effective, as rules for matching words in French can be applied.</p>
<p>If the application requires dimension search to work in multiple languages, this is a preferable approach, since the dimension values themselves will be translated into the available interface languages.  We can also maintain dimension ordering in the Endeca configuration, and dispense with any special user interface processing that might otherwise be required.  How the data is mapped into these dimensions, and what classification synonyms may be required still depends on how the inbound data is structured, but since we are maintaining the translated dimension values here, there is no harm in maintaining translations as appropriate.</p>
<h4>3.3	Record Language as a Property and/or Dimension</h4>
<p>Recall that in addition to the interface language, and the record language, we also need to consider the user&#8217;s interest languages.  The specifics of the application will dictate how the user&#8217;s interest languages are determined.  For example, they might be stored in a user profile, assigned by an administrator, or selected automatically based on the user&#8217;s interface language, locale, or other settings.</p>
<p>In order to provide the user with the appropriate options, the record language will need to be represented as a property and/or dimension value on each record.  This will allow the application to use the user&#8217;s interest language to filter their results accordingly.  This is achievable simply by making the record language a filter-enabled property.  However in many cases, especially when the user is allowed multiple interest languages, implementing the language as a dimension is more appropriate, as it brings all the power of Endeca dimensions &#8211; Guided Navigation based on language, refinement statistics, multi-valued selections, etc.</p>
<p>Just like the previous example of Geography, you will want to translate the dimension values for the Language dimension into multiple languages themselves!  Following our previous example, you could create a dimension called &#8220;en:Language&#8221;, one called &#8220;fr:Langue&#8221;, one called &#8220;es:Lengua&#8221;, etc.  These would contain values that correspond to the translations of the possible record languages into each of the possible interface languages.</p>
<div align="center">
        <img src="/article-assets/images/endeca_i18n/Figure3.png" border="0" alt="Fig. 3: Multiple Language Dimensions">
<p class="figure">
            <b><br />
              Figure 3:<br />
            </b> Multiple Language Dimensions</p>
</p></div>
<p>There are a few things to notice about this example.  First, notice that we have made the two-letter ISO language code a classifiable synonym for each dimension value.  This makes it easy to standardize the incoming data on using those codes for the record language.  Notice also that Italian is not one of the interface languages that we have created dimensions for, but it is listed as one of the dimension values.  This is because (in our hypothetical application) we are not offering an Italian translation of the user interface, but we do have some records in Italian that will be in our index.  It may often be the case that an application has a small number of interface languages, but a much larger number of record languages.</p>
<p>Manually creating all these dimension values for each interface language dimension in Dev Studio can be tedious, especially when there will be many different record languages in the index.  One option we have employed is to make these language dimensions autogenerated.  Then have a Java manipulator in your pipeline look at the two-character language code for each record and set the values for each of the Language dimensions to their appropriately localized value using the Java Locale object.  For example if the current record has &#8220;en&#8221; as its language, the manipulator sets a property called &#8220;fr_lang&#8221; to &#8220;Anglais&#8221;, &#8220;en_lang&#8221; to &#8220;English&#8221;, etc.  You need to store the set of available interface languages so your Java manipulator would know which languages to translate the two-letter code into.  Then you can map &#8220;en_lang&#8221; to &#8220;en:Language&#8221;, &#8220;fr_lang&#8221; to &#8220;fr:Langue&#8221;, etc.  If you unexpectedly get a document with a new record language, it would automatically show up in the language dimensions.  If you add a new interface language, however, you&#8217;d still need to create the new language dimension for it and update your list of interface languages for the Java manipulator so it would get populated appropriately.</p>
<h3>
        <a name="head1" class="section">Rendering the User Interface</a><br />
    </h3>
<p>In the scenario where we create a language-specific dimension for each logical dimension in our index, we will then need to filter the dimensions displayed to the user so that only those corresponding to the user&#8217;s interface language are displayed.</p>
<h4>Delegating to the User Interface?</h4>
<p>The simplistic way to do this is to issue a query that returns all dimensions, and delegate to the user interface the job of only displaying the ones appropriate for a user&#8217;s selected interface language.  If we&#8217;re sticking to a naming convention like the one shown above for our dimensions, this is straightforward to implement.  In this case, the user interface simply displays only the dimensions that are prefixed with the code that matches the user&#8217;s interface language.</p>
<p>However, this may have an extremely detrimental affect on application performance.  If our application has 20 available interface languages, we are (nearly) multiplying the amount of work that the MDEX engine has to do and the amount of information being transferred over the network by 20 for every query that is executed.</p>
<h4>Optimizing the Query</h4>
<p>A slightly more involved, but much more performant solution is to take advantage of the <code>setSelection()</code> method of the <code>ENEQuery</code> object to specify which properties and dimensions to compute and return.  The dimensions returned for a given user can be restricted to those matching the user&#8217;s chosen interface language. It may be necessary for the application to dynamically determine and/or cache which dimensions are appropriate for which interface languages so that it can take full advantage of the reduction in MDEX engine work and network bandwidth.</p>
<p>You should also set the language for each query that you send to Endeca using the <code>setLanguageId()</code> method of the <code>ENEQuery</code> object.  For example if you know you are querying only French documents, set the query language to &#8220;fr&#8221; so French stemming will be used in the search.</p>
<h3>
        <a name="head1" class="section">Conclusion</a><br />
    </h3>
<p>As you can see from some of the complexities we&#8217;ve discussed, properly internationalizing an Endeca-powered application can be full of new and interesting challenges.  I hope this article has provided a helpful head start for those embarking on such an endeavor.  If you have any questions or comments, I encourage you to comment on this article.</p>
<p>    <well_formed_html><br />
        <a name="references"></a><br />
    </well_formed_html></p>
<h3>
        <a name="head1" class="section">References</a><br />
    </h3>
<ol>
<li>
                <a href="http://en.wikipedia.org/wiki/List_of_ISO_639-2_codes" target="_1">ISO 639-2 codes</a>
            </li>
</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/endeca-i18n/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Introduction to Documentum Composer</title>
		<link>http://www.bluefishgroup.com/2008/an-introduction-to-documentum-composer/</link>
		<comments>http://www.bluefishgroup.com/2008/an-introduction-to-documentum-composer/#comments</comments>
		<pubDate>Fri, 10 Oct 2008 11:00:00 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Custom ECM Solutions]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=368</guid>
		<description><![CDATA[Overview As part of the new Documentum 6 platform, EMC has introduced Documentum Composer, a new application for packaging and deploying Documentum artifacts. It is meant to replace Documentum Application Builder and Documentum Application Installer with a single application for developing, building, and deploying Documentum projects into a repository. It is important to note that [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Overview</a><br />
    </h3>
<p>
            As part of the new Documentum 6 platform, EMC has introduced Documentum Composer, a new application for<br />
            packaging and deploying Documentum artifacts. It is meant to replace Documentum Application Builder and<br />
            Documentum Application Installer with a single application for developing, building, and deploying<br />
            Documentum projects into a repository.
        </p>
<p>
            It is important to note that Composer is a completely new application, built from scratch using the Eclipse<br />
            platform. It improves upon DAB and DAI in a number of ways, including an open, standardized XML file format;<br />
            a more robust and customizable compilation and installation paradigm; and improved visibility for developers<br />
            into the application&#8217;s operation and data.
        </p>
<p>
            Overall, Composer is a huge leap forward for the Documentum installation paradigm, but it is still maturing<br />
            as an application. In many cases, Composer will prove a more useful tool than DAB or DAI, but there are<br />
            probably still cases where DAB and DAI might be needed, at least temporarily, where Composer&#8217;s functionality<br />
            or reliability fall short. Careful planning and attention to detail can help to make Composer a valuable<br />
            tool for predictable, repeatable installation into Documentum repositories, despite some of the gaps and<br />
            pitfalls still present.
        </p>
<p>
            This article aims to provide an initial introduction to the Composer application, including some core<br />
            concepts, a discussion of major changes from the world of DAB and DAI, and some tips and tricks to make<br />
            using Composer easier and less problematic.
        </p>
<p class="note">
        <b>Note: </b><br />
            This article was written based on Documentum Composer 6.0 SP1. Subsequent Composer versions are known<br />
            to improve on some of the shortcomings identified here.
        </p>
<h3>
        <a name="head2" class="section">Core Concepts</a><br />
    </h3>
<h4>Artifact</h4>
<p>
            An<br />
            <i><b>artifact</b></i><br />
            is a single unit of Composer code which usually describes a single object to be installed into a Documentum<br />
            repository. An artifact might be a custom object type, a document, an ACL, a user, a group, or any number of<br />
            other Documentum objects.
        </p>
<p>
            An artifact can be imported into a Composer project from an existing repository, or it can be created from<br />
            scratch using various Composer editors and local file system content.
        </p>
<h4>Project</h4>
<p>
            A<br />
            <i><b>project</b></i><br />
            is a single, installable collection of artifacts. It corresponds roughly to the DocApp concept from the<br />
            DAB/DAI world. The only way to install artifacts into a repository using Composer is to install a Composer<br />
            project containing those artifacts. Unlike DAB/DAI, it is not possible to manually checkout or checkin<br />
            individual artifacts using Composer; one must install the entire project into the repository.
        </p>
<p>There are a number of ways to create and populate a project using Composer:</p>
<ul>
<li>A project can be imported into Composer from an existing repository project or DocApp.</li>
<li>A project can be imported from an existing Composer project on the file system.</li>
<li>
                A project can be created from scratch using artifacts from a repository as well as artifacts created<br />
                from scratch.
            </li>
</ul>
<h4>Workspace</h4>
<p>
            One big improvement over DAB/DAI is that Composer provides support for keeping multiple projects open at the<br />
            same time, by way of the Eclipse workspace paradigm. A<br />
            <i><b>workspace</b></i><br />
            is a collection of projects which can be viewed and developed actively at the same time within a single<br />
            instance of Composer.
        </p>
<p>
            Although composer does not prevent you from dragging and dropping artifacts from one project to another,<br />
            it is NOT supported. In some cases it will work, but in most cases necessary prerequisites, dependencies,<br />
            or installation parameters will be lost. Always examine the XML for any artifacts that have been dragged<br />
            and dropped into a Composer project, to be certain that locations and other references are intact and<br />
            correct. It may be necessary to clean and build your project to discover some problems, while others<br />
            will not be evident until installation or later.
        </p>
<p class="note">
        <b>Note: </b><br />
            It is strongly recommended to keep your Composer workspace separate from any other Eclipse workspaces that<br />
            may already exist.
        </p>
<h4>Installation Parameters</h4>
<p>
            In order to make it possible to drive certain installation behavior based on parameters entered at the time<br />
            of installation, Composer utilizes<br />
            <i><b>installation parameters</b></i><br />
            . An installation parameter can be created to represent a folder location, for example, and then that<br />
            location can be entered at runtime when installing the project into a repository.
        </p>
<p>
            Some features of Composer require installation parameters in order to function, but in these cases the<br />
            parameter is created and given a default value automatically. In other cases, you may wish to create your<br />
            own installation parameters.
        </p>
<p>
            If a project utilizes multiple installation parameters, it can be useful to provide values for all of these<br />
            parameters using a single file. This file is called an<br />
            <i><b>Installation Parameter File</b></i><br />
            , and it can be specified as part of the installation wizard.
        </p>
<h3>
        <a name="head3" class="section">Major Changes from DAB/DAI</a><br />
    </h3>
<p>
            Overall, Composer is a vast improvement over DAB/DAI, because it provides so much more visibility into and<br />
            control over what is happening every step of the way. The architecture is far more robust and extensible,<br />
            and this can only mean good things for the future of Documentum configuration management.
        </p>
<p>
            The application is still maturing, however, and it shows. There are still many ways to accidentally &#8220;break&#8221;<br />
            your artifacts or your project. Some much-needed custom editors are still missing, occasionally requiring<br />
            manual editing of XML which is error-prone and time-consuming. Other editors are buggy or not fully<br />
            functional, and at times the installation parameters functionality can be unreliable. Hopefully these issues<br />
            will be addressed in future releases.
        </p>
<p>Some of the key improvements and changes are discussed below.</p>
<h4>Open File Formats</h4>
<p>
            All artifacts that make up a Composer project are represented using a standardized XML file format.<br />
            Documentum has abandoned the proprietary DAB/DAI file formats, which completely obfuscated their contents.<br />
            The new XML-based files provide visibility into what is in the project, making it easier to troubleshoot and<br />
            resolve problems. Furthermore, the XML format makes it simple to track and compare revisions to your<br />
            Composer project using source control.
        </p>
<h4>Eclipse Platform</h4>
<p>
            You might be familiar with the Eclipse Integrated Development Environment (IDE), which is popular among Java<br />
            developers for a variety of reasons. But Eclipse is more than just an IDE; it is also a powerful open-source<br />
            software development platform upon which a wide variety of rich client applications can be built.
        </p>
<p>
            Composer is built on the Eclipse platform, and the installation includes a bundled Eclipse environment.<br />
            Composer is deployed as a set of Eclipse plugins within this embedded Eclipse environment, such that running<br />
            the <code>eclipse.exe</code> executable automatically launches Composer.
        </p>
<div align="center">
        <img src="/article-assets/images/composer/composer_main_window_512.jpg" border="0" alt="Fig. 1: Composer Main Window">
<p class="figure">
            <b><br />
              Figure 1:<br />
            </b> Composer Main Window</p>
</p></div>
<p>
            Composer leverages the<br />
            <a target="_blank" href="http://www.eclipse.org/modeling/emf/">Eclipse Modeling Framework</a><br />
            (EMF), which is &#8220;a powerful modeling framework and code generation facility for building tools and other<br />
            applications based on a structured data model&#8221;. Like the rest of the Eclipse platform, EMF is open source.<br />
            It provides a wide variety of modeling and code generation capabilities which enable Composer to be<br />
            leveraged across multiple platforms and environments.
        </p>
<p>
            Although it is possible to run Eclipse-based applications as plugins within your Eclipse IDE, it is not<br />
            recommended to install the Composer plugins directly into an existing Eclipse environment in this way.<br />
            Composer is meant to run within its own separate installation of Eclipse.
        </p>
<h4>Compilation Paradigm</h4>
<p>
            One of the benefits of the Eclipse platform is that it offers a number of paradigms that are familiar to<br />
            developers. Composer utilizes the standard Eclipse build paradigm, with its own custom builder, in order to<br />
            provide real-time validation and compilation of artifacts before they are installed. Composer Projects must<br />
            be &#8220;built&#8221; before being &#8220;installed&#8221;, enabling offline discovery of some problems before attempting to<br />
            install into the repository.
        </p>
<p>
            The project directory structure is broken out in support of this compilation paradigm, with separate<br />
            directories for artifact source code, artifact content, and compiled binaries. Refer to the<br />
            <a href="#head4">Anatomy of a Composer Project</a><br />
            section for a full discussion of the project directory structure.
        </p>
<p>
            By default, Eclipse is configured to automatically build your Composer project, which means that as artifact<br />
            source files are saved, Eclipse will attempt to compile the project and will report validation or<br />
            compilation problems. If you Clean your project, all compiled resources will be deleted and rebuilt<br />
            automatically. If you turn off automatic compilation, you will need to remember to manually build the<br />
            project. If you attempt to install your project, it will be built automatically.
        </p>
<div align="center">
        <img src="/article-assets/images/composer/composer_project_menu.jpg" border="0" alt="Fig. 2: Composer Project Menu">
<p class="figure">
            <b><br />
              Figure 2:<br />
            </b> Composer Project Menu</p>
</p></div>
<p>
            The<br />
            <b>Problems</b><br />
            tab reports errors, warnings, and informational messages reported while compiling the artifacts in your<br />
            project. These kinds of problems typically mean something is wrong with your artifacts or their metadata.
        </p>
<div align="center">
        <img src="/article-assets/images/composer/composer_problems_tab_517.jpg" border="0" alt="Fig. 3: Composer Problems Tab">
<p class="figure">
            <b><br />
              Figure 3:<br />
            </b> Composer Problems Tab</p>
</p></div>
<p>
            The<br />
            <b>Error Log</b><br />
            tab reports errors encountered within the Composer or Eclipse code. Errors point to a Composer bug or<br />
            configuration problem, and are typically unrelated to your project. Many errors are simply informational<br />
            and do not adversely affect Composer&#8217;s execution. Composer 6.5 minimizes the prevalence of these errors<br />
            as compared with Composer 6.0.
        </p>
<div align="center">
        <img src="/article-assets/images/composer/composer_error_log_tab_510.jpg" border="0" alt="Fig. 4: Composer Error Log Tab">
<p class="figure">
            <b><br />
              Figure 4:<br />
            </b> Composer Error Log Tab</p>
</p></div>
<h4>Installation Paradigm</h4>
<p>
            In the DAB/DAI world, DocApps and DocApp artifacts could be checked out and checked in. In Composer, the<br />
            paradigm is one of &#8220;installation&#8221;, with no explicit control over checkout/checkin of individual artifacts.<br />
            This means it is not possible to manually checkout and checkin project artifacts to and from the repository<br />
            without installing the entire project.
        </p>
<p>
            To install a Composer project, right click on the project in the Navigator pane, and select<br />
            <b>Install Documentum Project&#8230;</b>
    </p>
<div align="center">
        <img src="/article-assets/images/composer/composer_project_context_menu.jpg" border="0" alt="Fig. 5: Composer Project Context Menu">
<p class="figure">
            <b><br />
              Figure 5:<br />
            </b> Composer Project Context Menu</p>
</p></div>
<p>
            Selecting<br />
            <b>Install Documentum Project&#8230;</b><br />
            will launch the project installation dialog, which gathers installation options prior to installing the<br />
            project to a repository. You must first login to a repository before the wizard will allow you to continue.
        </p>
<div align="center">
        <img src="/article-assets/images/composer/composer_project_installation_wizard.jpg" border="0" alt="Fig. 6: Composer Project Installation Wizard">
<p class="figure">
            <b><br />
              Figure 6:<br />
            </b> Composer Project Installation Wizard</p>
</p></div>
<h4>Better Logging</h4>
<p>
            Another major improvement over DAB/DAI is Composer&#8217;s logging. Composer provides much better and more<br />
            detailed logging of every activity, as well as full Java stack traces when something goes wrong. Together<br />
            these provide greater visibility into what&#8217;s happening as it is happening.
        </p>
<p>
            Whereas DAB/DAI provided decent logging of the installation process, there was no logging of compilation or<br />
            other activities taking place while working on a project, such as import or modification of existing<br />
            artifacts. Composer provides logging for all of these activities, making it much easier to track down issues<br />
            before they make it into a repository.
        </p>
<p>
            Composer&#8217;s log file can be found in the <code>%TEMP%/documentum</code> directory. Composer creates a new<br />
            log for every Composer session, so it is typically most expedient to sort the directory by date and look<br />
            at the most recent log file found.
        </p>
<h4>Headless Eclipse Mode</h4>
<p>
            Composer can be run in &#8220;headless Eclipse mode&#8221;, which enables command-line scripting and automation of<br />
            project installation. This feature, new to Composer, provides for self-contained, fully automated deployment<br />
            of projects into a repository, without the need for a previous DFC installation or DMCL client.
        </p>
<h3>
        <a name="head4" class="section">Anatomy of a Composer Project</a><br />
    </h3>
<h4>Files and File Types</h4>
<p>There are a variety of files and file types that make up a Composer project.</p>
<ul>
<li>
                Eclipse project files (<br />
                <code>*.project</code>,<br />
                <code>*.classpath</code>)
            </li>
<li>
                Composer project files (<br />
                <code>*.dmproject</code>,<br />
                <code>*.template</code>)
            </li>
<li>
                Artifact XML source files (<br />
                <code>*.aliasset</code>,<br />
                <code>*.module</code>,<br />
                <code>*.aspecttype</code>,<br />
                <code>*.folder</code>,<br />
                <code>*.format</code>,<br />
                <code>*.group</code>,<br />
                <code>*.jardef</code>,<br />
                <code>*.javalibrary</code>,<br />
                <code>*.job</code>,<br />
                <code>*.lifecycle</code>,<br />
                <code>*.method</code>,<br />
                <code>*.module</code>,<br />
                <code>*.acl</code>,<br />
                <code>*.procedure</code>,<br />
                <code>*.relation</code>,<br />
                <code>*.relationtype</code>,<br />
                <code>*.role</code>,<br />
                <code>*.sysobject</code>,<br />
                <code>*.type</code>, and so forth)
            </li>
<li>
                Installation Parameter definition files (<code>*.parameter</code>)
            </li>
<li>
                Content files (<code>*.*</code> in the <code>/content</code> subdirectory)
            </li>
<li>
                DAR Definition file (<code>*.dardef</code> in the <code>/dar</code> subdirectory)
            </li>
<li>
                Compiled artifact files (<code>*.artifact</code> in the <code>/bin</code> subdirectory)
            </li>
<li>
                Compiled DAR file (<code>*.dar</code> in the <code>/bin-dar</code> subdirectory)
            </li>
</ul>
<h4>Folder Structure</h4>
<p>
            Each Composer project is broken down into a standard folder structure, with different folders serving<br />
            different purposes. Some folders contain XML source code, some contain content files, and others contain<br />
            compiled descriptors and binaries. The project folder structure can be seen in the Navigator pane of<br />
            Composer.
        </p>
<div align="center">
        <img src="/article-assets/images/composer/composer_navigator.jpg" border="0" alt="Fig. 7: Composer Navigator Pane">
<p class="figure">
            <b><br />
              Figure 7:<br />
            </b> Composer Navigator Pane</p>
</p></div>
<h4>Hidden Resources</h4>
<p>
            By default, the Composer interface hides certain resources that are not part of the core user-facing<br />
            functionality. It can sometimes be useful to reveal these hidden resources in order to troubleshoot and<br />
            resolve problems, but ordinarily it is best to keep these resources hidden to avoid tampering with them<br />
            inadvertantly.
        </p>
<p>
            In order to function properly, Composer relies on a hidden project that it creates in your workspace<br />
            automatically the first time you try to create a new project. This hidden project is called<br />
            <i><b>DocumentumCoreProject</b></i>, and it must be present in your workspace in order<br />
            for Composer to function properly.
         </p>
<p class="note">
        <b>Note: </b><br />
            If you wish to create a new workspace, simply moving your custom projects into it will not be sufficient.<br />
            You must also move the DocumentumCoreProject, or else let Composer create a new one by creating a new<br />
            project.
        </p>
<p>
            In order to reveal the hidden DocumentumCoreProject and other hidden resources, launch the Filters dialog<br />
            from the pulldown menu in the upper right corner of the Navigator pane.
        </p>
<div align="center">
        <img src="/article-assets/images/composer/composer_navigator_pulldown.jpg" border="0" alt="Fig. 8: Composer Navigator Pane Pulldown Menu">
<p class="figure">
            <b><br />
              Figure 8:<br />
            </b> Composer Navigator Pane Pulldown Menu</p>
</p></div>
<p>
            The Filters dialog can be used to enable or disable various filters, which will have the effect of hiding or<br />
            revealing various resources in the Navigator pane.
        </p>
<div align="center">
        <img src="/article-assets/images/composer/composer_filters_dialog.jpg" border="0" alt="Fig. 9: Composer Filters Dialog">
<p class="figure">
            <b><br />
              Figure 9:<br />
            </b> Composer Filters Dialog</p>
</p></div>
<div align="center">
        <img src="/article-assets/images/composer/composer_filters_dialog_show_all.jpg" border="0" alt="Fig. 10: Composer Filters Dialog with All Filters Disabled">
<p class="figure">
            <b><br />
              Figure 10:<br />
            </b> Composer Filters Dialog with All Filters Disabled</p>
</p></div>
<p>
            The Navigator pane shown below has had all filters disabled, revealing all hidden projects, folders, and<br />
            files.
        </p>
<div align="center">
        <img src="/article-assets/images/composer/composer_navigator_show_all.jpg" border="0" alt="Fig. 11: Composer Navigator Panel with All Filters Disabled">
<p class="figure">
            <b><br />
              Figure 11:<br />
            </b> Composer Navigator Panel with All Filters Disabled</p>
</p></div>
<h4>Folders</h4>
<p>
            The<br />
            <code>/Artifacts</code><br />
            folder contains the XML artifact &#8220;source files&#8221; from which your Composer project is built.
        </p>
<p>
            The<br />
            <code>/content</code><br />
            folder contains the binary and other content files used to back artifacts that require content, such as<br />
            documents. The folder structure within the<br />
            <code>/content</code><br />
            folder is created automatically by Composer as content is imported into the project from repositories and<br />
            the local file system. The<br />
            <code>/content</code><br />
            folder structure is based on a hash structure, but it is possible to move a content file to a more<br />
            user-friendly location within your project by updating the content location reference in the artifact XML<br />
            file for the artifact. This can be useful in order to provide well-defined content locations within your<br />
            project, so that an Ant build, for example, could deposit updated BOF JARs or customized XML files into the<br />
            content location, then easily install the project containing those artifacts into a repository.
        </p>
<p>
            The folders below contain &#8220;compiled&#8221;<br />
            <code>.artifact</code><br />
            files, built based on the XML and other project metadata described above. These folders would typically NOT<br />
            be checked in to source control or distributed in a source code package.
        </p>
<ul>
<li>
            <code>/dfs-bin</code>
        </li>
<li>
            <code>/dfs-gen-src</code>
        </li>
<li>
            <code>/bin-dar</code>
        </li>
<li>
            <code>/bin</code>
        </li>
</ul>
<p>
            The<br />
            <code>/dar</code><br />
            folder contains XML source required by the project as a whole, including an object type definition and<br />
            default installation settings for the project.
        </p>
<ul>
<li>
            <code>dmc_dar.type</code><br />
                XML describing the dmc_dar object type, which is needed in order to install a project into a repository.<br />
                The contents of this file typically do not need to be edited directly.
            </li>
<li>
            <code>default.dardef</code><br />
                XML describing various default settings to use for installation into a repository. This file contains<br />
                references to many other artifacts, and can sometimes require editing in order resolve broken references<br />
                or to include missing artifacts.
            </li>
</ul>
<p>
            The<br />
            <code>/src</code><br />
            folder is created automatically by Composer. By default it is empty. It may be possible to leverage this<br />
            folder to develop Java source code to be used by your project, but this is beyond the scope of this article.
        </p>
<p>
            The<br />
            <code>/Installation Parameter Files</code><br />
            folder is created automatically by Composer. By default it is empty, but it can be used to develop parameter<br />
            files containing parameter values to be used upon installation.
        </p>
<h3>
        <a name="head5" class="section">More About Artifacts</a><br />
    </h3>
<h4>Artifact Editors</h4>
<p>
            Composer includes custom editors for a wide variety of Documentum artifacts. These editors enable you to<br />
            specify the artifact metadata and configuration using intuitive controls. Composer comes preconfigured to<br />
            utilize custom editors for all of the following artifacts:
        </p>
<ul>
<li>Alias Sets</li>
<li>Aspect Modules</li>
<li>Aspect Types</li>
<li>Formats</li>
<li>Installation Parameters</li>
<li>Jar Definitions</li>
<li>Java Libraries</li>
<li>Jobs</li>
<li>Lifecycles</li>
<li>Methods</li>
<li>Modules</li>
<li>Permission Sets</li>
<li>Procedures</li>
<li>Relation Types</li>
<li>SysObjects</li>
<li>Types</li>
</ul>
<p>
            There are additional artifacts for which there are no custom editors. Some of these artifacts are hidden,<br />
            while others are not. It is much easier to create these artifacts by importing them from an existing<br />
            repository, but if necessary they can be created from scratch by editing XML files. These include Folders<br />
            and Relations, among others.
        </p>
<h4>Artifact XML</h4>
<p>
            In some cases the editors are insufficient or unstable, in which case it becomes necessary to edit the XML<br />
            source directly, using the <b>System Editor</b> or <b>Text Editor</b>. To open any artifact using an<br />
            editor other than the default, simply right-click on the artifact and select <b>Open With</b>.
        </p>
<div align="center">
        <img src="/article-assets/images/composer/composer_artifact_context_menu.jpg" border="0" alt="Fig. 12: Composer Artifact Context Menu">
<p class="figure">
            <b><br />
              Figure 12:<br />
            </b> Composer Artifact Context Menu</p>
</p></div>
<p>
            The list below provides an overview of some of the key XML elements and attributes you may need to work<br />
            with.
        </p>
<ul>
<li>
            <code>sysObjects</code><br />
                This element can be found within the &lt;dataModel&gt; element within an artifact&#8217;s XML, typically a<br />
                folder artifact. It specifies which objects should be linked into that folder. The references here must<br />
                correspond to artifacts within your project.
            </li>
<li>
            <code>location</code><br />
                This attribute can be found within the URL specified by the href attribute of the &lt;sysobjects&gt;<br />
                element. It defines the folder path in the repository where this artifact should be linked, if<br />
                applicable. Sometimes this value must be manually updated to change the location an artifact is linked,<br />
                but don&#8217;t forget to update the &lt;sysObject&gt; element references to the artifact in the corresponding<br />
                folder&#8217;s artifact XML, or the location change may not work!
            </li>
<li>
            <code>artifactURI</code><br />
                This attribute can be found within the URI specified by the uri attribute of the<br />
                &lt;Artifact:Artifact&gt; element. It is a unique identifier which has no purpose other than to uniquely<br />
                identify the artifact within the project. If your artifact was imported from an existing repository,<br />
                this value will be the folder path from that repository. If your artifact was imported from the file<br />
                system, this value will be the path to the content on the local file system. It is okay if this value<br />
                refers to a location that is no longer available &#8212; it is an identifier only and is not used to specify<br />
                any installation locations.
            </li>
<li>
            <code>filePath</code><br />
                This attribute of the &lt;contentStore.contentEntries.value&gt; element specifies the path within the<br />
                project to the binary content file to use for this artifact. This value can be modified directly in the<br />
                XML to point to a well-defined location, rather than the default location defined by Composer; just be<br />
                sure the location you enter corresponds to real content.
            </li>
</ul>
<h3>
        <a name="head6" class="section">Some Technical Details</a><br />
    </h3>
<h4>Version Compatibility</h4>
<p>
            It is important to understand which versions of Composer, DAB, and DAI are capable of interacting with<br />
            certain repository versions.
        </p>
<p>
            Composer provides support for all of the following situations, although in some cases an interim &#8220;migration<br />
            repository&#8221; must be used.
        </p>
<ul>
<li>Create a new Composer project by importing a 5.3 DocApp archive on a file system</li>
<li>Create a new Composer project by importing a 5.3 DocApp from an existing 5.3 repository</li>
<li>Create a new Composer project by importing a 5.3 DocApp from an existing 6.0 repository</li>
<li>Create a new Composer project by importing an existing Composer project</li>
<li>Install a Composer project into a 5.3 repository.</li>
<li>Install a Composer project into a 6.0 repository.</li>
</ul>
<p>
            For more details concerning DocApp migration, consult the<br />
            <b>Migrating a repository DocApp</b><br />
            and<br />
            <b>Migrating a DocApp Archive</b><br />
            sections of the EMC Documentum Composer Version 6 SP1.5 User Guide.
        </p>
<p>
            Alhough Composer is a great new paradigm shift, it is one which is still incomplete. Because of this, EMC is<br />
            still supporting DAB and DAI, and has released a version of DAB/DAI which is supported against both 5.x and<br />
            6.x repositories. To interact confidently with both D5 and D6 repositories, you must use version<br />
            <b>5.3 SP5.5 Update 1</b><br />
            of DAB and DAI.
        </p>
<h4>Source Control</h4>
<p>
            One of the benefits of Composer&#8217;s new XML file format for artifact source is that it is now possible to<br />
            track an artifact&#8217;s version history by checking the artifact&#8217;s XML source file directly into a source<br />
            control system as changes are made.
        </p>
<p>
            In DAB/DAI, there were no source files representing the artifacts, and indeed the only view into these that<br />
            could be generated outside a repository was a DocApp archive, which was made up of binary files that could<br />
            not be easily compared or reviewed. This made it necessary to track an artifact&#8217;s version history directly<br />
            in the repository where it was installed and versioned, which was often insufficient and very limiting.
        </p>
<p>With Composer, it is simple to manage the entire Composer project source in a source control system.</p>
<h4>Automated Build and Deployment</h4>
<p>
            Another benefit of the Composer model is the ability to script the compilation and deployment of a project<br />
            and its artifacts. This makes it possible to develop truly integrated scripts for building and deploying<br />
            Documentum projects in an automated fashion. As this model matures, we should start to see projects with<br />
            fully integrated Ant or Maven scripts for building Java source code and then utilizing the output of that<br />
            build to deploy updated JARs and other artifacts into a repository.
        </p>
<p>
            This automation capability will make it easy for development teams to automatically deploy new software<br />
            releases to the repository, in addition to any automated deployment to application servers, method servers,<br />
            and elsewhere.
        </p>
<h3>
        <a name="head7" class="section">Tips and Tricks</a><br />
    </h3>
<ul>
<li>
                In certain situations, it may be necessary to inspect and modify the artifact XML files in order to<br />
                resolve various problems or work around certain Composer limitations. Ordinary usage, however, should<br />
                not require delving into the XML.
            </li>
<li>
                When importing folders and objects, you must also import the folders containing those folders and<br />
                objects, all the way up to the root cabinet, or you risk the folders being linked into the application<br />
                folder instead of the location you intended.
            </li>
<li>
                Composer does not seem to be capable of installing folders with a specific ACL set on them &#8212; only<br />
                SysObject seem to allow ACL specification.
            </li>
<li>
                ACLs set on Folders imported from another repository will NOT be preserved when imported into the<br />
                Composer project. You must rely on installation parameters to set ACLs on objects.
            </li>
<li>
                Installing a BOF module will unlink/unconfigure any previously installed BOF module with the same name<br />
                automatically.
            </li>
<li>
                Composer logs almost everything it does to a temporary log file in<br />
                <code>%TEMP%/documentum</code>. Each Composer session starts a new log file in this folder, so often the best way to see the most<br />
                recent log is simply to sort the files in the folder by date and look at the most recent one.
            </li>
<li>
                Often Composer will report an error in the UI, but without much detail. In these cases it can be useful<br />
                to look in the log. The number of misleading errors should be reduced in Composer 6.5.
            </li>
<li>
                Composer sometimes reports success when in fact there has been an error along the way. It is therefore<br />
                recommended that you always review the log file after any major activity, especially the installation of<br />
                a project into repository.
            </li>
<li>
                When moving from one version of Composer to another, the recommended approach is to create a new<br />
                workspace, import your Composer projects into that new workspace, and do a clean build.
            </li>
</ul>
<h3>
        <a name="head8" class="section">Conclusion</a><br />
    </h3>
<p>
            Composer is a powerful new development platform for building Documentum projects. Although it is still<br />
            maturing and may not be right for every project, for those willing to invest some time to understand its<br />
            capabilities and limitations, Composer offers a level of flexibility and visibility that until now has not<br />
            been possible when building and deploying artifacts into a Documentum repository.
        </p>
<h3>
        <a name="head9" class="section">Additional Resources</a><br />
    </h3>
<p>For additional reading, try the following documentation:</p>
<ul>
<li>EMC&reg; Documentum&reg; Composer Version 6.0 SP1.5 User Guide (P/N 300005253A02)</li>
<li>EMC&reg; Documentum&reg; Composer Version 6.0 SP1.5 Release Notes (P/N 300006232A02)</li>
<li>EMC&reg; Documentum&reg; Composer Version 6.0 SP1 Plugin Developer Guide (P/N 300006231A01)</li>
<li>
                EMC&reg; Documentum&reg; Composer Version 6.0 SP1 Language Pack Installation and Release Notes (P/N<br />
                300006233A01)
            </li>
<li>
            <a target="_blank" href="http://paulcwarren.wordpress.com/2008/08/11/creating-dfs-services-using-documentum-composer/"><br />
                    Creating DFS Services Using Documentum Composer<br />
                </a><br />
                (from Paul Warren&#8217;s blog)
            </li>
<li>
            <a target="_blank" href="http://paulcwarren.wordpress.com/2008/05/29/documentum-composer-integrating-bof-development-into-your-workflow/"><br />
                    Documentum Composer: Integrating BOF Development into your workflow<br />
                </a><br />
                (from Paul Warren&#8217;s blog)
            </li>
<li>
            <a target="_blank" href="http://paulcwarren.wordpress.com/2008/02/19/installing-documentum-composer-on-the-web-tools-project/"><br />
                    Installing Documentum Composer on the Web Tools Project<br />
                </a><br />
                (from Paul Warren&#8217;s blog)
            </li>
<li>
            <a target="_blank" href="https://community.emc.com/tags/composer?communityID=2013"><br />
                    Items tagged with &#8216;Composer&#8217;<br />
                </a><br />
                within the Documentum community on EDN
            </li>
</ul>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/an-introduction-to-documentum-composer/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Creating A Photo Library Using Web Publisher Categories</title>
		<link>http://www.bluefishgroup.com/2008/creating-a-photo-library-using-web-publisher-categories/</link>
		<comments>http://www.bluefishgroup.com/2008/creating-a-photo-library-using-web-publisher-categories/#comments</comments>
		<pubDate>Fri, 10 Oct 2008 11:00:00 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Web Content Management]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=367</guid>
		<description><![CDATA[Introduction Blue Fish&#8217;s Web Content Management consultants are frequently asked to build something that brings an extra little spice and twist to a client&#8217;s website or Intranet. In doing so, the goal is always to build an elegant technical solution that can be easily administered by our client using Documentum&#8217;s Web Publisher. The more straight [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Introduction</a><br />
    </h3>
<p>Blue Fish&#8217;s Web Content Management consultants are frequently asked to build something that brings an extra little spice and twist to a client&#8217;s website or Intranet. In doing so, the goal is always to build an elegant technical solution that can be easily administered by our client using Documentum&#8217;s Web Publisher. The more straight forward and simple the solution, the more likely our clients will be to adopt it and be able to support it. Often, it is the simple solution that results in an elated client.</p>
<p>One recent variation on a typical WCM solution was when we were asked to design and build a solution for a client&#8217;s corporate intranet photo library. While the intranet would allow employees to browse for forms, policies, news, and events just like any other website, the photo library would allow employees to click through image categories to find relevant pictures. This client, like so many others, had loads of images &#8211; of sites, community projects, machinery, logos, workers in the field, etc &#8211; spread across file shares, one off image hosting solutions by department, and even on CDs in shoe boxes and filing cabinets. </p>
<p>Instead of using Flickr or some other off the shelf solution that would have drawn all these digital assets together into one nice location for the employees, the client asked for two things:</p>
<ol>
<li>The photo library had to be neatly integrated into the intranet; Why should the employees leave the intranet to visit Flickr or a file share to find an image?</li>
<li>The administration of the photos had to take place in Web Publisher; Why make content administrators learn another system other than Web Publisher specifically for the photo library?</li>
</ol>
<p>Additionally, it was obvious that sometimes an image could be categorized multiple ways, so the photo library had to support a hierarchy of categories across which an image could be tagged multiple times. </p>
<p>In the discussion that follows, I&#8217;ll show you how we designed a solution that uses Documentum Web Publisher to meet those requirements. Armed with Web Publisher and knowledge of web applications, perhaps your next WCM solution can incorporate a little something special &#8212; like a photo library.</p>
<h3>
        <a name="head2" class="section">Solution Overview</a><br />
    </h3>
<p>Our client really wanted employees to browse and download digital images on the intranet, not on another website or file share. The experience of &#8220;leaving&#8221; the intranet to download a corporate logo was going to cause user adoption problems for both the intranet and the photo library. Additionally, the new design for the intranet looked great &#8211; so why not wrap the photo library with the same look and feel as the rest of the site?</p>
<p>All the pages on the intranet, like all well designed WCM solutions, featured a variety of common elements such as a header, footer, breadcrumbs and side bar navigation.</p>
<div align="center">
        <img src="/article-assets/images/webpub_categories_photo_library_01.jpg" border="0" alt="Fig. 1: Common elements on an intranet page">
<p class="figure">
            <b><br />
              Figure 1:<br />
            </b> Common elements on an intranet page</p>
</p></div>
<p>We were able to create a photo library that reused these common components while employees browsed the image categories.</p>
<div align="center">
        <img src="/article-assets/images/webpub_categories_photo_library_02.jpg" border="0" alt="Fig. 2: Common elements on the photo library category page">
<p class="figure">
            <b><br />
              Figure 2:<br />
            </b> Common elements on the photo library category page</p>
</p></div>
<p>Maintaining the common look and feel, these elements were all still present when a user chose a category and was selecting images from the thumbnail gallery view.</p>
<div align="center">
        <img src="/article-assets/images/webpub_categories_photo_library_03.jpg" border="0" alt="Fig. 3: Common elements on the photo library thumbnail gallery page">
<p class="figure">
            <b><br />
              Figure 3:<br />
            </b> Common elements on the photo library thumbnail gallery page</p>
</p></div>
<p>Additionally, the client wanted the administration of the photo library to be handled within Web Publisher. Web Publisher&#8217;s out of the box category functionality was the perfect solution for implementing the administrative tools for the photo library due to the following category capabilities: </p>
<ol>
<li>Web Publisher&#8217;s categories are easily created to reflect the hierarchal taxonomy required for the photo library. Each category has as many children, grand children, and deeper descendents as needed by the client&#8217;s changing business needs. 	Alternatively, a category can be a single node with no children at all.</li>
<li>Web Publisher allows any web content maintained in Web Publisher to be linked to multiple categories with just a few simple clicks.</li>
<li>Web Publisher&#8217;s interface requires no customization to allow content administrators to create, edit, and delete categories. Additionally, no modifications are needed to allow content administrators to associate images with any number of photo gallery 	categories.</li>
</ol>
<p>It was just a matter bringing the following components of the solution together to create an easily administered gallery that looked and felt as great as the rest of the intranet!</p>
<h4>Category Creation and Administration in Web Publisher</h4>
<p>Take a look at any out of the box deployment of Documentum Web Publisher and you&#8217;ll notice the <i>Categories</i> node in the left hand side of the application. The <i>Functional Taxonomy</i> node is a child of the <i>Categories</i> node and is how the templates are organized. By selecting a template category, an administrator is shown the documents created using the template or templates in that category. </p>
<p>To create the hierarchal taxonomy of the photo library, a sibling to the <i>Functional Taxonomy</i>, named <i>Photo Library</i> (Figure 4), needs to be created under the <i>Categories</i> node. The <i>Functional Taxonomy</i> node allows users browse web content associated with specific templates and, thus, functional categories. Similarly, through the new taxonomy node, users will be able to browse photo library images associated with specific photo library categories. Once the taxonomy node is created, the library category hierarchy can quickly be created using standard Web Publisher functionality.</p>
<div align="center">
        <img src="/article-assets/images/webpub_categories_photo_library_04.jpg" border="0" alt="Fig. 4: Photo Library Taxonomy Node with Children Categories">
<p class="figure">
            <b><br />
              Figure 4:<br />
            </b> Photo Library Taxonomy Node with Children Categories</p>
</p></div>
<p>When creating new gallery categories, an administrator can not only name the category but set the display title, locale specific translations, and permissions. </p>
<div align="center">
        <img src="/article-assets/images/webpub_categories_photo_library_05.jpg" border="0" alt="Fig. 5: Creating a new category">
<p class="figure">
            <b><br />
              Figure 5:<br />
            </b> Creating a new category</p>
</p></div>
<div class="callout">
<p>
            <b>Tip</b>
        </p>
<p>Web Publisher requires that the <i>Category Name</i> be unique. You can use the <i>Title</i> attribute for displaying duplicated names while keeping the <i>Category Name</i> as the unique identifier. </p>
</p></div>
<p>Once the photo library taxonomy structure is defined under the Categories node, there are a few remaining steps.</p>
<p>First, the administrator must associate this new taxonomy with a Web Cabinet. This step only needs to be done once when the initial taxonomy is created and setup. Apply the taxonomy to a Web Cabinet from the Web Cabinets tab of the taxonomy&#8217;s properties view. </p>
<div align="center">
        <img src="/article-assets/images/webpub_categories_photo_library_06.jpg" border="0" alt="Fig. 6: Associating the Photo Library taxonomy with a Web Cabinet">
<p class="figure">
            <b><br />
              Figure 6:<br />
            </b> Associating the Photo Library taxonomy with a Web Cabinet</p>
</p></div>
<p>Subsequent changes to the taxonomy structure (for example, when a user creates a new gallery category) won&#8217;t change this association.</p>
<p>Once the taxonomy is associated with a Web Cabinet, Web Publisher will publish the structure as an XML file to a Taxonomy folder under the Web Cabinet. This XML file can be promoted and published to the Web Server to be consumed and displayed on the final website.</p>
<div align="center">
        <img src="/article-assets/images/webpub_categories_photo_library_07.jpg" border="0" alt="Fig. 7: Web Cabinet with the published XML file">
<p class="figure">
            <b><br />
              Figure 7:<br />
            </b> Web Cabinet with the published XML file</p>
</p></div>
<div class="callout">
<p>
            <b>Tip</b>
        </p>
<p>The published XML defines each category similar to the sample below. The categories are ordered in the XML based on when the categories were created, not alphabetically.</p>
<p>By associating and applying an XSL presentation file, the category sort order can be altered prior to publishing to the Web Server. </p>
</p></div>
<pre>
        <code>

&lt;category name="Argentina_sites" className="Generic" 
    type="dm_category" internalId="0b000405800073a8"&gt;
   &lt;details title="Argentina"&gt;
      &lt;description&gt;&lt;/description&gt;
      &lt;owners&gt;
         &lt;owner name="dmadmin"/&gt;
      &lt;/owners&gt;
      &lt;operations/&gt;
      &lt;languageInfo/&gt;
   &lt;/details&gt;
   &lt;category name="Argentina Operations" className="Generic" 
       type="dm_category" internalId="0b000405800073b7"&gt;
      &lt;details title=""&gt;
         &lt;description&gt;&lt;/description&gt;
         &lt;owners&gt;
            &lt;owner name="dmadmin"/&gt;
         &lt;/owners&gt;
         &lt;operations/&gt;
         &lt;languageInfo/&gt;
      &lt;/details&gt;
   &lt;/category&gt;
&lt;/category&gt;</code>
    </pre>
<p>For our client&#8217;s photo library solution, we created a .NET web control that consumed an alphabetically sorted XML file on a Web Server and displayed the category structure as a photo library &#8220;site map&#8221; on the intranet.</p>
<div align="center">
        <img src="/article-assets/images/webpub_categories_photo_library_08.jpg" border="0" alt="Fig. 8: The photo library XML consumed and rendered on the intranet">
<p class="figure">
            <b><br />
              Figure 8:<br />
            </b> The photo library XML consumed and rendered on the intranet</p>
</p></div>
<h4>Associating images with categories</h4>
<p>Now that the structure of the photo library categories has been created and published and is consumable XML on the website, the solution needs to allow a content administrator to tag an image as belonging to one or more categories.</p>
<p>Web Publisher allows a user to associate web content with an existing category a few different ways:</p>
<ol>
<li>Select the category and create the new content from the category view. This ensures that the content will be related to both the Functional Taxonomy (via the template used for the content creation) as well as the Photo Library category.</li>
<li>Create or import the web content using any other manner. Then, from the Properties view, select the &#8220;Categories&#8221; tab and associate the image with the category or categories.</li>
</ol>
<div align="center">
        <img src="/article-assets/images/webpub_categories_photo_library_09.jpg" border="0" alt="Fig. 9: The Categories Tab on an existing piece of Web Content">
<p class="figure">
            <b><br />
              Figure 9:<br />
            </b> The Categories Tab on an existing piece of Web Content</p>
</p></div>
<p>That&#8217;s it! Provided the SCS publishing configuration is set to export the relationships, the <code>dm_relation</code> of type <code>dm_category_assign</code> will be published when the content is published. </p>
<h4>Displaying the gallery</h4>
<p>Now the solution has an easily modified, published, and consumed XML representation of the photo library category structure. Additionally, the solution provides a simple mechanism to associate images with one or more categories. All that is missing is some website code &#8211; in the form of a JSP, taglib, .NET control, or other mechanism &#8211; to display the images that have been associated with a selected category.</p>
<p>For our client&#8217;s solution, Blue Fish created a simple ASPX page that read the category ID from the Request URL, queried the published web content metadata, and rendered the associated images in a thumbnail gallery view. Because the published XML representation of the photo library categories contains the names and titles as well as the unique ID, it was straightforward to embed the ID in the clickable links of &#8220;site map&#8221; view discussed earlier.</p>
<div align="center">
        <img src="/article-assets/images/webpub_categories_photo_library_10.jpg" border="0" alt="Fig. 10: Thumbnail Gallery View">
<p class="figure">
            <b><br />
              Figure 10:<br />
            </b> Thumbnail Gallery View</p>
</p></div>
<h3>
        <a name="head3" class="section">Closing Thoughts and Considerations</a><br />
    </h3>
<p>In addition to creating a photo library, a similar solution could be created to catalog any type of file &#8211; or mixed media types including photos, video, and audio. Another enhanced solution would allow further detail to be collected about each image. Instead of 		associating the image directly to a category, an image &#8220;detail&#8221; template could be used to capture additional metadata including a description, long title, separate scaled thumbnail image, and more. This web content would be associated with the category. Using this 		metadata, the thumbnail gallery view could display even more details. </p>
<p>The possibilities for enhancing a WCM solution using Web Publisher&#8217;s out of the box category functionality are numerous. Given a little planning and preparation, the discussion in this article can help turn an ordinary web experience into something a bit unique.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/creating-a-photo-library-using-web-publisher-categories/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Avalanche of Articles</title>
		<link>http://www.bluefishgroup.com/2008/avalanche-of-articles/</link>
		<comments>http://www.bluefishgroup.com/2008/avalanche-of-articles/#comments</comments>
		<pubDate>Tue, 23 Sep 2008 00:41:45 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=364</guid>
		<description><![CDATA[The Blue Fish article factory has been operating at peak production lately. Here are several new articles that the team has written over the past several weeks. Automate BOF Module Deployment During Development &#8211; Steve has a great article on how to streamline development cycle times by automating the deployment of Documentum BOF modules. Introduction [...]]]></description>
				<content:encoded><![CDATA[<p>The Blue Fish article factory has been operating at peak production lately. Here are several new articles that the team has written over the past several weeks.</p>
<ul>
<li><a href="http://www.bluefishgroup.com/library/2008/bof-ant-task/">Automate BOF Module Deployment During Development</a> &#8211; Steve has a great article on how to streamline development cycle times by automating the deployment of Documentum BOF modules.</li>
<li><a href="http://www.bluefishgroup.com/library/2008/wdk-test-framework/">Introduction to the WDK Automated Test Framework</a> &#8211; Thomas Hughes has reviewed the new WDK Automated Test Framework.</li>
<li><a href="http://www.bluefishgroup.com/library/2008/web-publisher-usability/">Improving Web Publisher Usability</a> &#8211; Lisa Hill shares some of our tricks for making Web Publisher easier to use.</li>
<li><a href="http://www.bluefishgroup.com/library/2008/bullet-proof-markup-designing-for-content-management-systems/">Bullet Proof Markup: Designing for Web Content Management Systems</a> &#8211; Alex Bilstein writes about how to design your HTML markup to work best with a WCM system.</li>
<li><a href="http://www.bluefishgroup.com/library/2008/using-lifecycle-state-extensions/">Using Documentum Lifecycle State Extensions</a>Glen Tarrant writes about how to add custom functionality to lifecycles via lifecycle state extensions</li>
<li><a href="http://www.bluefishgroup.com/library/2008/introduction-to-documentum-irm-services/">Introduction to Documentum IRM Services</a> &#8211; Terence McDevitt gives us an overview of Documentum&#8217;s Information Rights Management solution which can keep people from reading your documents even after they are exported from the docbase.</li>
<li><a href="http://www.bluefishgroup.com/library/2008/enabling-high-availability-monitoringxml/">Enabling High Availability for a Complex Documentum Based Application</a> &#8211; Jamie Balling explains how he&#8217;s been able to increase application uptime by integrating some custom monitoring components into his solution.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/avalanche-of-articles/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Enabling High Availability for a Complex Documentum Based Application</title>
		<link>http://www.bluefishgroup.com/2008/enabling-high-availability-monitoringxml/</link>
		<comments>http://www.bluefishgroup.com/2008/enabling-high-availability-monitoringxml/#comments</comments>
		<pubDate>Fri, 29 Aug 2008 11:00:00 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Custom ECM Solutions]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=363</guid>
		<description><![CDATA[Overview For the past several months, I&#8217;ve been working on a global enterprise content management solution Blue Fish built for a Fortune 100 client. The system serves as the document repository for tens of thousands of sales and marketing users, spanning dozens of countries and supporting eight languages. This is a critical business application that [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Overview</a><br />
    </h3>
<p>For the past several months, I&#8217;ve been working on a global enterprise content management solution Blue Fish built for a Fortune 100 client. The system serves as the document repository for tens of thousands of sales and marketing users, spanning dozens of countries and supporting eight languages. This is a critical business application that is always being used by someone somewhere. There is no room for application outages and documents must always be available.</p>
<p>The solution relies heavily on Documentum, and a number of services and features are critical to proper functioning. These include:</p>
<ul>
<li>The Documentum Content Server</li>
<li>Site Caching Services (SCS)</li>
<li>SCS Post-Syncronization Scripts</li>
<li>Documentum Workflows</li>
<li>Media Transformation Services (MTS)</li>
<li>Web Publisher and Documentum Administrator</li>
<li>The Documentum LDAP Synchronization Job</li>
</ul>
<p>Due to the necessary complexity of the overall system, we knew that a dedicated support group and an industry-leading monitoring solution would be required to ensure smooth operations. We therefore worked with our client to ensure that the IT infrastructure was robust and launched the application with a suite of monitors which confirm that machines are up, that services are running, and so forth. However, we soon found that this type of high-level monitoring was not sufficient given the complexity and criticality of the application.</p>
<p>This article gives some insight into the challenges we encountered and the solutions we implemented to monitor this critical application. Please note that this article assumes familiarity with some technical aspects of Documentum.</p>
<h3>
        <a name="head2" class="section">Support Infrastructure and Challenges</a><br />
    </h3>
<p>As previously mentioned, the application has a dedicated support team which utilizes a monitoring tool called <a href="http://www.empirix.com/products-services/contact_center.asp">OneSight from Empirix</a>. This tool has the ability to monitor typical server statistics, such as availability, memory usage, disk usage, etc. It also has the ability to monitor Windows services and check URLs for expected responses.</p>
<p>Even though we launched with monitors for nearly every service, machine, and website involved in the architecture, this monitoring proved insufficient. Several production issues arose which highlighted weaknesses in the monitoring infrastructure. For example, we found cases where service monitors were showing success even though the service was hung, and we found instances where HTTP monitors showed success when the web component they were monitoring had critical errors.</p>
<p>Although Documentum provides out of the box notifications for notable repository events, such as job failures, these didn&#8217;t meet our needs, either. In the client&#8217;s environment, these notifications are directed to an email address which is intended to be checked regularly by the support team. In practice, this was difficult to manage. The appropriate response from the support team can vary drastically depending upon the severity of the problem being reported, and often times high priority notifications would get lost among less important ones. Also, reviewing an email inbox introduced a manual delay and increased possibility for human error.</p>
<p>Finally, given all the integration points across the system, the team sometimes had trouble answering the question of whether there were any issues across the system and pinpointing a component which was not functioning properly.</p>
<h3>
        <a name="head3" class="section">Monitoring Solution Overview</a><br />
    </h3>
<p>In response to these challenges, we took a big picture view of the architecture and designed a monitoring solution. This solution leveraged the existing monitoring infrastructure, but added custom monitoring components tightly integrated with the system to provide insight into whether things are not only running, but are successfully performing their functions.</p>
<p>The monitoring solution still utilizes Empirix for monitoring non-application-specific things. This includes machine availability, CPU usage, memory usage, free hard disk space, and so forth.</p>
<p>For monitoring items that are more tightly coupled to application logic and architecture, we created a custom application health dashboard. This dashboard was simple to create and consists of a single JSP page served by the web application itself. The data for the dashboard comes from a collection of monitoring modules (implemented as java classes) which perform business-level checks on the components for which they are targeted. Each of these monitoring modules reports a status of OK, warning, or failure and is displayed as a row on the dashboard. The dashboard also displays an overall application status which represents a rollup of certain critical modules.</p>
<p>We then setup URL monitors in Empirix for our application health which hit this application health dashboard and inspect the page for certain key strings, such as &#8220;APPLICATION STATUS: FAILED&#8221;. When these monitors detect a failure, they create support queue items for the support team. Individual modules can be queried to allow fine grain monitoring and severity reporting. In the case where the overall application status shows as failed, we report at the highest severity.</p>
<div align="center">
        <img src="/article-assets/images/enabling_highavail_screensh.jpg" border="0" alt="Fig. 1: Screen shot of Application Health Page">
<p class="figure">
            <b><br />
              Figure 1:<br />
            </b> Screen shot of section from application health page</p>
</p></div>
<p>Although this custom monitoring solution does indeed overlap with some capabilities of the traditional monitoring tools, it provides distinct benefits which greatly improve the supportability of the system. The solution provides a focused view of the application health and also gives the business team visibility as they wouldn&#8217;t normally have access to back-end monitoring systems. This helps them better communicate and manage issues. The solution also provides the application team greater control over monitoring. They have the best understanding of the severity and impact of specific application component issues, and the dashboard gives them immediate insight which helps expedite resolution of issues.</p>
<h3>
        <a name="head4" class="section">Documentum Integration Points</a><br />
    </h3>
<p>The monitoring solution is broadly scoped, covering almost all of the external processes and application components that interact with the core Documentum services. However, to keep the discussion focused, the rest of this article focuses on the strategies employed for monitoring the Documentum components.</p>
<h4>Content Server</h4>
<p>The support team had already setup Empirix monitors for the Content Server host and Windows service. We augmented this with a module that establishes a connection to the repository and executes a simple query via Documentum Foundation Classes (DFC). This connectivity is verified whenever the application health page is served by the web application, and it therefore provides confidence that each app server instance (there are several that run in a clustered environment) is successfully communicating with the content server.</p>
<h4>Site Caching Services (SCS) Publishing Jobs</h4>
<p>There are several SCS publishing jobs which push out several types of data from the content server for consumption by the web application and other application components. These jobs publish taxonomies (from Content Intelligence Services), web content, and -most critically-documents which have been approved for distribution. Implementing monitoring for these publishing jobs was especially important, as multiple issues had been experienced where publishing jobs failed or hung, and the support team wasn&#8217;t aware until users started complaining!</p>
<p>To prevent this problem, we built a generic module that can check on the status of any web publishing job. This module has logic which queries the repository tables to determine the status of the last run for the job. Furthermore, it compares the time of the last successful run against a time threshold configured in the application. If the job hasn&#8217;t run within the expected timeframe, a failure is reported.</p>
<p>Some additional effort was required to retrieve accurate publishing job status from the repository. The publishing configuration object (dm_webc_config) is updated with the time of the last full publish and the time of the last successful incremental run. However, this object is not updated when the job runs but there is no data to publish.  This presents a problem for our monitoring solution as we don&#8217;t want to &#8220;cry wolf&#8221; just because there was nothing to do! Therefore, this monitor also queries the job table (dm_job) to retrieve the last completion time and job status. The job status will be &#8220;COMPLETED&#8221; if it ran successfully.</p>
<h4>SCS Post-Synchronization Script Execution</h4>
<p>Some of the SCS jobs kick off post-sync scripts that ensure that application caches are kept up to date when new content and metadata are published. These critical scripts are kicked off by specifying a parameter in the &#8220;agent.ini&#8221; file on the SCS target machine. In our case, the script executes a java process.</p>
<p>We built logic into this java process to reports on its status by recording success and error events to a special &#8220;application health event&#8221; table in the database.  We have a monitoring module which reads this table, determines when the job last ran, and reports a failure condition if it was unsuccessful. Since this process should be kicked off after the publishing job runs, we also check the time of the last publish to make sure it executes successfully within the expected time interval after that publish. If it hasn&#8217;t run, we report a failure.</p>
<h4>Java Method Server (for workflows)</h4>
<p>Documents posted to the system go through an approval workflow before they are made available to end users. To accomplish this, custom &#8220;methods&#8221; were developed and integrated with Documentum workflow steps. The Documentum architecture utilizes the Java Method Server (an embedded Tomcat web server) to trigger these methods.</p>
<p>Basic Empirix service monitoring was in place for this Tomcat instance, but it proved insufficient. On several occasions, the service appeared to be running successfully even though our custom methods were not being triggered successfully. </p>
<p>In response, we created an additional custom &#8220;health check&#8221; method. This method accesses the same application context object that the workflow methods utilize and confirms that it has been successfully initialized. It also performs a simple query to the docbase using DFC to verify that it is properly functioning. We then have a module which invokes this method to make sure it is functioning properly.</p>
<p>Here are the technical details of this monitor for those of you who like that kind of stuff :</p>
<p>The implementation of the health check method is straightforward. In the &#8220;execute&#8221; function, we perform our checks and throw an exception in case of any errors. This exception will cause the method server to report that the launch failed. The implementation of the monitoring module is a little more involved&#8230;It utilizes DFC to create an IDfSession and calls the &#8220;apply()&#8221; function. We pass the &#8220;DO_METHOD&#8221; API command and the name of our health check custom method as arguments to this function. This function returns an IDfCollection which includes the attributes &#8220;launch_failed&#8221; and &#8220;timed_out&#8221;. If either of these attributes has a value of &#8220;T&#8221; we report a failure.</p>
<h4>Media Transformation Services</h4>
<p>Media Transformation Services (MTS) is a Documentum product that falls under the &#8220;Content Transformation Services&#8221; umbrella. The system utilizes MTS for a couple of specialized functions such as thumbnailing and assembling PowerPoint presentations. </p>
<p>MTS has its own dedicated machine and services, so we setup Empirix monitors to make sure these things are up and running. We also added a health check module which checks the size of the MTS &#8220;queue&#8221;. We determine what is in this queue by querying the dm_queue table for rows with a name of &#8220;dm_mediaserver&#8221;, which is the standard name for media server entries. We report an error if we can&#8217;t access the queue or we determine that the queue size is building up without any reductions over a configured time interval. </p>
<h4>LDAP Synchronization Job</h4>
<p>The system is used in a large corporate environment and utilizes LDAP to retrieve user and group information from Active Directory. We rely on the LDAP Synchronization job, which is an out-of-the-box job used to keep user accounts up to date in Documentum.</p>
<p>We have not yet implemented custom monitoring targeted at this component. When the job fails, the standard Documentum notification email is sent to the email address defined for the Content Server. So far, this has been acceptable, but there is room for improvement. The job has failed and we have had issues with particular user accounts as a result. We plan to add a module which leverages the logic used to monitor our publishing jobs. It would query the dm_job table for the time of the run and status for that job.</p>
<h4>Web Publisher and Documentum Administrator</h4>
<p>Web Publisher and Documentum Administrator are instrumental components of the system, and their availability is therefore critical to the overall health of the system.  We have found that standard Empirix monitors setup to monitor the machines and web servers have done a fine job keeping tabs on the health of these two components.</p>
<h3>
        <a name="head5" class="section">Conclusion</a><br />
    </h3>
<p>If there is one major theme from our experiences supporting this application, it is:</p>
<p>
        <well_formed_html><br />
            <span style="text-align:center; color:blue; font-style:italic"><strong>&#8220;Running&#8221; does not necessarily mean &#8220;working&#8221;!</strong></span><br />
        </well_formed_html>
    </p>
<p>Many monitoring systems simply determine whether a machine is up or a process is running, but this simplistic approach to monitoring only tells half the story (if that!).  Make sure your monitoring confirms that critical application components are actually doing what they are supposed to do. </p>
<p>Application monitoring should grow and improve as experience with the application mounts: when problems occur which expose blind spots in the monitoring solution, learn from them and improve the monitoring to ensure a more robust and stable system.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/enabling-high-availability-monitoringxml/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Introduction to Documentum IRM Services</title>
		<link>http://www.bluefishgroup.com/2008/introduction-to-documentum-irm-services/</link>
		<comments>http://www.bluefishgroup.com/2008/introduction-to-documentum-irm-services/#comments</comments>
		<pubDate>Fri, 29 Aug 2008 11:00:00 +0000</pubDate>
		<dc:creator>Terence McDevitt</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Custom ECM Solutions]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=362</guid>
		<description><![CDATA[Overview As content becomes more readily accessible to enterprise users, it also becomes more difficult to control distribution, particularly in situations where content is shared outside of the corporate network. This is especially concerning when the nature of the content could give competitive advantage to outside parties. In order to minimize the potential impact of [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Overview</a><br />
    </h3>
<p>As content becomes more readily accessible to enterprise users, it also becomes more difficult to control distribution, particularly in situations where content is shared outside of the corporate network.  This is especially concerning when the nature of the content could give competitive advantage to outside parties.</p>
<p>In order to minimize the potential impact of sensitive data falling into the wrong hands, organizations are looking to implement Information Rights Management (IRM) solutions.  IRM allows companies to gain tighter control of how content is distributed both within the organization and external via partners, vendors, and customers.</p>
<p>EMC Documentum provides the leading platform for storing and managing content in the market.  With a recent acquisition, Documentum now includes IRM capabilities in its product offering.  These services ensure that Documentum is able to provide a truly secure content management and distribution system.</p>
<h3>
        <a name="head2" class="section">What is IRM?</a><br />
    </h3>
<p>Traditionally, organizations have approached data security by ensuring that malicious persons or entities are kept out of the network and resources attached to it.  This type of security paradigm is known as <i><b>perimeter security</b></i>.  While this approach has served the enterprise well, it does not cover situations in which persons within the organization are sharing sensitive data to unauthorized users outside of the network (e.g. emailing, FTPing, etc.)</p>
<p>
        <i><b>Information Rights Management</b></i> (IRM) attempts to solve this problem by securing the content, not just the resources that house the content like file servers or web sites.  With IRM, enterprises can mark selected content as protected and authorize select users or groups of users to perform specific actions on the content, including copying, printing, and emailing.  Any request to perform an action on protected content is first sent to the IRM policy server, along with the credentials of the person attempting the action.  If the policy server determines that the user&#8217;s action is authorized, the content is unlocked and the user can finish their work.  Otherwise, the user is denied from acting on the content.</p>
<p>A typical example of where IRM&#8217;s power becomes apparent involves a content author working in an office application such as Microsoft Word.  Prior to IRM, authors wishing to &#8220;lock down&#8221; their content either used the built-in password protection in Word or third-party encryption tools.  In either case, the user needed to provide information to consumers as to how to open the protected content.  With IRM, authors can take advantage of plug-ins built into their applications allowing them to protect content and assign rights policies.  Consumers receiving this protected content need not know how to unprotect it.  This responsibility is left up to the IRM client embedded in their applications (this client communicates with the policy server to determine if the user has the rights to unprotect the content).</p>
<p>Information Rights Management generally encompasses the following concepts:</p>
<ul>
<li>
                <strong>Principals</strong> &#8211; IRM defines Principals as those entities that are authorized to perform given actions on content.  Typically, a Principal is a user on the network.  In some IRM implementations, a Principal could be a group of users, another network (e.g. a partner) or a resource on the network such as a mobile device.</li>
<li>
                <strong>Policies</strong> &#8211; Policies define what actions are acceptable for a given piece of content and a particular Principal or set of Principals.  Some IRM products can also allow content owners to create policies which revoke content privileges that were once established.  For example, a Sales and Marketing group may release a product&#8217;s data sheet and make it available for printing by the sales team.  If a new release of the product is introduced, the Sales and Marketing content owners can revoke rights on the old version of the product data sheet, forcing the sales team to request the latest copy.</li>
<li>
                <strong>Encryption</strong> &#8211; Content that is considered &#8220;protected&#8221; under IRM generally has strong encryption applied to it.  This encryption prevents unauthorized users from making any sense of the data.  Content encrypted with IRM products can only be unlocked using valid encryption keys known to the IRM policy server and the authorized client.</li>
</ul>
<h3>
        <a name="head3" class="section">Documentum IRM Services</a><br />
    </h3>
<p><h4>History</h4>
</p>
<p>In 2006, EMC Documentum entered into the IRM space with its acquisition of Authentica.  At the time of the purchase, Authentica was amongst the leading players in the relatively immature IRM market (SealedMedia and Liquid Machines being other notables).  In addition to its stand-alone IRM offering, Authentica also provided support for products like Microsoft Office.  This integration allowed for users to easily create IRM protected content from tools they were already familiar with.  EMC&#8217;s purchase of Authentica was in line with their bigger picture plan of tying together the storage, software and security portions of the business.  EMC clearly saw the benefits of rights management in the enterprise, and reeling in Authentica would complete the security picture between Content Server and enterprise users.</p>
<p><h4>Architecture</h4>
</p>
<p>Documentum IRM services can be deployed in an enterprise with incredible ease (although planning for this is a much larger task &#8211; see &#8220;Considerations&#8221; below).  The core component, IRM Server, only requires connectivity to a database server for storing policy and key information.  Enterprise users can easily encrypt content via a number of clients that securely connect to the Server.  Finally, enterprise services can leverage the Documentum IRM software development kit (SDK) to programmatically encrypt/decrypt sensitive content.  Refer to Figure 1 for a contextual diagram of a typical IRM Services architecture.</p>
<div align="center">
        <img src="/article-assets/images/irm-services/documentum-irm-services-architecture.jpg" border="0" alt="Fig. 1: Documentum IRM Services Architecture">
<p class="figure">
            <b><br />
              Figure 1:<br />
            </b> Documentum IRM Services Architecture</p>
</p></div>
<p>Three key components make up the IRM Services architecture:</p>
<div class="indent">
<p>
            <strong>Documentum IRM Server</strong><br />
			This is the foundation of the overall IRM service.  The IRM Server is responsible for storing policies that indicate what Principals can do, as well as for issuing a usage license when protected content is opened (A usage license tells the IRM client what the user can do with the content and how long the user has rights to the content).  In addition to storing policies, the Policy Server also stores keys that were used to originally encrypt the content.  When a user attempts to open protected content, a secure call is made to the Policy Server.  If the user has the correct permissions (according to the stored policy), the Server passes back the key that can be used to decrypt the content.  Typically, the IRM Server is deployed behind the corporate firewall.
		</p>
</p></div>
<div class="indent">
<p>
            <strong>Documentum IRM Clients</strong><br />
			When users want to protect content, they typically do so using a variety of clients provided by Documentum.  These clients make a secure connection to the Policy Server, which provides encryption keys and a policy for the content.  After successfully communicating with the Policy Server, the client applies the policy to the content and encrypts it using the key provided by the Server.  In addition to facilitating the creation of protected content, these clients are also responsible for determining whether or not a user can open protected content.  Documentum currently provides clients for the following:</p>
<ul>
<li>
                    <i>Microsoft Office (Word, Excel, PowerPoint)</i>
                </li>
<li>
                    <i>Microsoft Outlook</i>
                </li>
<li>
                    <i>Adobe Acrobat</i>
                </li>
<li>
                    <i>RIM Blackberry</i>
                </li>
</ul>
</p></div>
<div class="indent">
<p>
            <strong>Documentum IRM Repository Server</strong><br />
			IRM Repository Server used to be known as Authentica Content Security Server.  It is ideal for organizations who want to expose protected content to outside parties such as vendors, partners, or even potential customers.  IRM Repository Server actually stores protected content and allows for document creators to send messages to target recipients.  These users will then get links back to the protected content stored in the IRM Repository Server (at which point these users will have to identify themselves).  In addition, IRM Repository Server provides several web services that external applications can connect to in order to stream protected content over a secure connection.  It is important to distinguish between IRM Repository Server and Documentum Content Server.  Content Server manages the lifecycle of enterprise content.  IRM Repository Server is intended to serve up secure content that is published from within the enterprise.  For example, a Sales and Marketing team will use Content Server to create, review and edit a new marketing presentation intended for clients who have signed an NDA.  Sales and Marketing will then protect and publish that presentation using IRM Repository Server.  Clients will securely connect the IRM Repository Server to obtain an IRM protected copy of the presentation.
		</p>
</p></div>
<p><h4>Features</h4>
</p>
<p>Documentum got several IRM features &#8220;out of the box&#8221; with the purchase of Authentica.  Included in these features:</p>
<ul>
<li>
                <strong>Dynamic Rights</strong> &#8211; A key feature in the Documentum IRM offering is the ability to change document policies on the fly.  Imagine a scenario where a document owner decides to give a vendor access to a document.  When the vendor opens the document, the Documentum IRM Policy Server is contacted to determine if the user opening the document has the appropriate rights to do so.  Now suppose that the vendor&#8217;s partnership agreement expires.  The content creator can revoke the user&#8217;s permissions without having to modify or delete the user&#8217;s copy of the content.  This notion of dynamic policy assignment is critical for enterprises wishing to truly manage access to content that is distributed outside of the corporate network.</li>
<li>
                <strong>Offline Rights Management</strong> &#8211; Documentum IRM Services provides functionality to allow offline usage of content, while continuing to respect any policies that have been defined for the document.  For example, documents can be made available to users with set expiration dates.  Once a user has authenticated against the document&#8217;s policy, IRM Services embeds this information in the document and will self destruct the content at the specified expiration date.</li>
<li>
                <strong>Stand-Alone Product</strong> &#8211; While Documentum IRM Services integrates with the existing Documentum product line, the IRM Services component is a stand-alone product.  Thus, customers do not need to have Documentum in place in order to take advantage of the features provided in IRM Services.</li>
<li>
                <strong>Plug-Ins for Common Office Applications</strong> &#8211; Documentum provides a number of plug-ins that allow end users to define IRM policies for documents they create in applications such as Word, Outlook, Excel, PowerPoint and Adobe Acrobat.  There is even a plug-in for RIM Blackberry devices for users needing to access IRM protected content on the go.</li>
<li>
                <strong>Support for Dynamic Watermarks</strong> &#8211; Documentum IRM Services allows protected documents to carry watermarks, which are useful for identifying the status of a printed document (e.g. &#8220;Confidential&#8221;, &#8220;Draft&#8221;, etc.).  In addition to standard watermarks, Documentum IRM Services can place dynamic watermarks on documents when certain actions are taken.  For example, if a user prints a document, IRM Services can embed a dynamic watermark on the content with the login name of the user who is printing the document.  Thus, if an unauthorized hard copy of the data is found, organizations can immediately track down those responsible.</li>
</ul>
<p>Since the Authentica acquisition, EMC has extended IRM Services to better integrate with the Documentum stack.  Some notable enhancements include:</p>
<ul>
<li>
                <strong>Direct Integration with Content Server</strong> &#8211; Documentum IRM provides rights management features from within Documentum Content Server.  This integration provides an easier means of applying IRM policies to documents with limited changes to existing Documentum-based architectures.  In addition, current business processes (e.g. workflows, lifecycles, etc.) can now take advantage of IRM with minimal modifications.</li>
<li>
                <strong>Software Development Kit (SDK)</strong> &#8211; Documentum provides an IRM Services SDK in order to allow third parties to extend IRM functionality to their own applications.  Access to this SDK should help facilitate any IRM customizations needed in an enterprise Documentum application.  As an example, an organization may have a custom desktop integration with Documentum.  In order for users to open IRM protected content, the desktop customization could utilize the SDK to pass the user&#8217;s credentials in to the Policy Server to determine whether or not the user should have rights to work with the content.</li>
</ul>
<h3>
        <a name="head4" class="section">Architectural Considerations with IRM</a><br />
    </h3>
<p>Roll out of an enterprise IRM solution is not something that happens overnight.  A tremendous amount of planning must go into the initiative, from infrastructure build-out with corporate IT to business change management for the users who will be interacting with IRM.  Here are some key points to consider when implementing an IRM solution:</p>
<ul>
<li>
                <strong>Sending Content over the Wall</strong> &#8211; While most organizations will want to exclude outside parties from accessing sensitive information, there are often situations where access must be granted.  For example, if a company is working closely with a manufacturing partner, it is very likely that content will be shared with that partner.  Documentum IRM Services can be deployed in a manner that keeps policy information secure, while still exposing services to the outside world (this could be done either by setting up IRM Server in a DMZ or having Repository Server directly serving protected content).  This decision should be made as early in the planning stages as is possible.</li>
<li>
                <strong>Enterprise Services Need to &#8220;Crack the Safe&#8221;</strong> &#8211; Large organizations typically have services that perform actions on content (full-text indexing for search, backup/recovery, etc.).  An enterprise wishing to roll out an IRM solution must understand at which point they want content protected.  If an IRM policy is applied when content is created, enterprise services such as indexing will need to have a way to unprotect that information when it is read.  Depending on the number of services, customizations required to decrypt data could derail the IRM initiative.  Organizations could consider protecting content at the point of distribution to alleviate this problem.</li>
<li>
                <strong>Who Controls the Policies?</strong> &#8211; Companies implementing an IRM solution are likely going to have a well-defined set of rules for when policies are applied to content and which rights principals will have to that content.  In this situation, the usage of policy templates helps ensure that users aren?t making the decision about what rights to give to whom.  Of course, this power can be left in the hands of the user if the company prefers.</li>
</ul>
<h3>
        <a name="head5" class="section">Summary</a><br />
    </h3>
<p>As the enterprise is increasingly becoming connected to the outside world via technologies such as email and web services, securing sensitive information is quickly showing up on CIOs&#8217; priority lists.  A key component to fulfilling an organization&#8217;s security mandate is to ensure that critical content remains under tight control of the enterprise, whether that content is distributed internally or externally.</p>
<p>Implementation of an Information Rights Management solution helps companies gain confidence that content is secure, no matter where it resides.  Documentum&#8217;s IRM Services provide a powerful solution to this problem, giving incredible management options for content.  In addition, IRM Services tightly integrates with existing tools and platforms within the enterprise such as Documentum Content Server and Microsoft Office.</p>
<p>With the continued demand for organizations to distribute content within the enterprise as well as outside the firewall, the need to control this content is ever increasing.  Information Rights Management attempts to fill this need by providing dynamic policy control that follows content, no matter where it goes.  While implementation of an enterprise-wide IRM initiative is a significant undertaking, with proper planning and execution, an organization can ensure that only the right people are able to view or manage sensitive information.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/introduction-to-documentum-irm-services/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Improving Web Publisher Usability</title>
		<link>http://www.bluefishgroup.com/2008/web-publisher-usability/</link>
		<comments>http://www.bluefishgroup.com/2008/web-publisher-usability/#comments</comments>
		<pubDate>Fri, 29 Aug 2008 10:20:45 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Web Content Management]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=361</guid>
		<description><![CDATA[Introduction For years, Web Publisher was the sole interface for Web Content Management solutions built on the Documentum platform. Recently, through the release of Page Builder and the Contributor UI, EMC has provided alternative interfaces to this core product aimed at simplifying the content authoring process. While these interfaces are great tools for certain types [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Introduction</a><br />
    </h3>
<p>For years, Web Publisher was the sole interface for Web Content Management solutions built on the Documentum platform.  Recently, through the release of Page Builder and the Contributor UI, EMC has provided alternative interfaces to this core product aimed at simplifying the content authoring process.  While these interfaces are great tools for certain types of content creation tasks, unfortunately, they do not replicate the full capabilities of Web Publisher.  For users that have to perform a wide variety of web content management tasks, Web Publisher is still the only tool available.</p>
<p>One of the biggest complaints of Web Publisher (and hence the push to develop alternative interfaces) has been that its usability is not up to par with other enterprise web content management tools.  With D6, EMC has begun to address this usability issue in Web Publisher itself with incremental usability enhancements.  For example, users will notice that with D6 the check boxes of the 5.3 stack have been removed and in place of them are right-click menus with CTRL- and SHIFT- click enabled multi-select.</p>
<div align="center">
        <img src="/article-assets/images/d6usability.jpg" border="0" alt="Fig. 1: D6 Web Publisher Interface Changes">
<p class="figure">
            <b><br />
              Figure 1:<br />
            </b> D6 Web Publisher Usability Enhancements</p>
</p></div>
<p>While these enhancements are welcome improvements, there is still much that can be done to make Web Publisher a more usable tool, both in D6 and on the legacy 5.3x stack.  This article will outline some of these simple enhancements and best practices that you can put in place today to better leverage your investment in Web Publisher (and hopefully give your users a nice sigh of relief)</p>
<h3>
        <a name="head2" class="section">Scoping Down Interface Elements</a><br />
    </h3>
<p>One of the easiest ways to make Web Publisher more useable is to simply reduce the amount of options that users see.  Much of the perceived problem with Web Publisher is not that the individual actions themselves are so difficult, but simply that there are too many choices &#8211; too many options from which users can select.  While proper use of the standard Web Publisher roles (content author, content manager, web developer, and administrator) can go a long way towards reducing the complexity for users that don&#8217;t need it, even greater impact can be had through smart application of security.</p>
<h4>Folder Security</h4>
<p>One way that users often interact with content is via the Web Cabinets.  This view allows users to browse a folder structure that houses content for the system.  Even if users don&#8217;t have access to the Web Cabinets node within Web Publisher explicitly, content authors frequently must browse the folder structure when creating links to other documents within the content editor.  A great way to reduce the complexity of the interface is to remove from view those folders in which users have no business poking.  For instance, nearly every site has some sort of folder structure for &#8220;includes files&#8221; &#8211; those artifacts that web developers maintain for the look and feel of the site (CSS, Javascript, headers, footers, etc.).  By simply restricting access to the root folder that houses these items, the interface has one less element for users to think about.  With a rich and robust security model (as well as a well thought out folder structure), this concept can often be greatly expanded to further reduce the folders that a given user encounters when browsing the web cabinets.  The fewer folders a user sees, the easier it is for them to find what they are looking for.</p>
<h4>Categories Security</h4>
<p>Another popular view for interacting with content within Web Publisher is the Categories view, or more specifically, the functional taxonomy.  This view has content organized by what &#8220;type&#8221; of page it is (according to the templates used to create the content).  A well structured functional taxonomy can be very powerful, allowing users to browse all &#8220;press releases&#8221; or &#8220;product pages&#8221; in one place regardless of how they might be organized on the physical website.</p>
<p>In any given site, there are often different types of users that interact only with certain types of pages.  For instance, certain users may be tasked to ONLY create press releases and are not working with any other type of content.  Further, certain templates (the home page for instance) might be restricted such that only trusted users have the ability to create content of this type.  If security is applied to the nodes in a well thought out category structure, users will only be presented with the categories that are relevant to them, reducing from the interface irrelevant options.  Not only does this improve the user&#8217;s experience, if you never show the option to a user to begin with, then your administrators don&#8217;t have to deal with the inevitable question of &#8220;why don&#8217;t I have access to that?&#8221;</p>
<h3>
        <a name="head3" class="section">Reduce the Number of Clicks</a><br />
    </h3>
<p>Everyone is busy these days &#8211; users want to get into the content management system, perform their tasks, and get out.  Unfortunately, Web Publisher is a &#8220;click&#8221; intensive application.  Anything that can be done to reduce the number of clicks a user has to perform in order to get their job done will be greeted with a huge welcome.  Over the years, we at Blue Fish have identified several clicks that can be removed regardless of the other details of the full solution.</p>
<h4>Auto-start in Classic View (5.3 only)</h4>
<p>If you have already moved to D6, then you can skip right over this suggestion.  If, on the other hand, you still are leveraging your investment in Web Publisher 5.3, then you are probably already familiar with the &#8220;Streamline&#8221; view.  The Streamline view can be considered Documentum&#8217;s first foray into addressing the usability concerns of the Web Publisher interface by providing an alternative way to navigate the repository.  Out of the box, Web Publisher 5.3 is configured such that the Streamline view is the default view into which a new user of Web Publisher is launched.  Unfortunately, most users find the &#8220;Classic&#8221; view much more useful. While a user always has the ability to set their user preferences up to start in the alternative Classic view, many users (especially novice ones) don&#8217;t know about this option and so are launched into the Streamline view every time they log in.  At best, this is an annoyance &#8211; at worst, something that can become so confusing that user adoption suffers.  A very simple customization can take away all of this concern, and just launch the users directly into the Classic view.</p>
<h4>Auto-start workflow if only one available</h4>
<p>Workflow is one of the most powerful concepts within Web Publisher.  While Web Publisher comes with a few sample workflows, these are often customized to create workflows that make sense for a given organization.  Having read through the section above on reducing interface elements, you can probably guess that I am also suggesting applying proper security to workflows &#8211; so that users only see the workflows that should be made available to them.  Once this is done, in many cases, the majority of users will only have one workflow available to them.  Yet when launching a workflow, Web Publisher always launches a dialog that forces the users to choose &#8220;which workflow&#8221; even if there is only one available.  My thought is, why give me a choice if there is only one option to choose?  A simple customization can make it such that when a user selects to &#8220;Start Workflow&#8221;, if there is only one workflow available, the system will just go ahead and launch that one.  No need to make a user pick if they really don&#8217;t have a choice anyway.</p>
<h4>Pre-check &#8220;Edit Now&#8221;</h4>
<p>When an author is creating new content, after selecting a template, they are taken to the new content attributes screen.  On this screen, users enter metadata for the content &#8211; things like the object name, title and keywords, in addition to any effective dates or expiration dates that should apply to the content.  At the bottom of this page is a check box with an inconspicuous &#8220;Edit Now&#8221; label. If users check this box, the template editor automatically launches when the user says OK to the content attributes.  If the user forgets to check this box, the new content attributes page is closed and the user has to locate and select their newly created content, and then launch the template editor manually.  Again, with a simple customization the &#8220;Edit Now&#8221; option can be checked by default so users are saved these unnecessary steps.  And if they ever didn&#8217;t want to launch the content editor, they could still uncheck the box &#8211; but for the 99% of cases where you actually want to launch the template editor, one less click required.</p>
<h3>
        <a name="head4" class="section">User Focused Template Design</a><br />
    </h3>
<p>Often when Blue Fish comes on board to work with a new client, it is not to create a new system from scratch, or even to port a solution from a legacy content management system into Documentum.  In fact, many times our clients have existing Web Publisher solutions in place, but they are just so hard to use that the business is ready to throw them out.  This isn&#8217;t the fault of the Web Publisher tool itself, but instead is the result of a few poor design choices in the implementation of the system.  One area in particular that tends to suffer is the templates themselves.</p>
<p>Documentum is improving the experience of working with Web Publisher templates by creating a richer in-context editing experience in newer versions of Page Builder, but even for those sites that are still leveraging the tried and true Web Publisher Editor templates, keeping the user experience in mind during development can go a long way towards creating a system that is so straightforward that an in-context editing experience (and the limitations that these solutions still impose) is simply not necessary for a highly usable content authoring system.</p>
<h4>Top-Bottom Layout</h4>
<p>We all know that when a user encounters a web page they will start reading at the top and work their way down.  We also know that users may get lazy on the way and loose interest, so information architects will tell you to place the most important items that you want them to see at the top, and then leave the ancillary information for the end of the page &#8220;below the fold&#8221;.  While this is implicitly obvious, it is an important part of web page design &#8211; and it should be a real consideration in template design as well.  The template should follow the same top-bottom design as the web page, with elements appearing in the form in the same order that they appear on the website.  Primary page information should come first, followed by auxiliary or sidebar content.  It may sound obvious, but when a content author is filling out that form, it should feel natural and map seamlessly to the fields on the page to create the best possible user experience.</p>
<div class="callout">
<p>
            <b></b>
        </p>
<p>Bonus Tip:  While you are at it, go ahead and include elements in the actual content template that may not be necessary (for instance, a &#8220;Read More&#8221; link that could be hard coded in the XSL now), but that you just know (or even think) that in the future user&#8217;s might want control.  Time and time again I see these sorts of requirements change, and it is a lot easier to add an extra element like this to the template now &#8211; in the proper order &#8211; and then just expose it in the rules file later.  The alternative is to write an instruction file to update all of your existing content and insert the new element in the correct spot, but I say if you can predict the element, go ahead and add it.</p>
</p></div>
<h4>Preview Format</h4>
<p>There are two primary mechanisms for an author to view their content changes from the template editor: Webview and Preview.  Webview is by far my recommended approach as this actually launches the current page on the WIP website, and you can see all changes within the full site context (header, footer, navigation, etc.).  Preview on the other hand, launches the rendered page within a Web Publisher preview application.  The drawback of this is that since it is not launching the actual website, those elements of the page that are determined by the site context could never be accurately portrayed.</p>
<p>The preview format can be very useful, however, in the case of templates that produce content fragments instead of full content pages.  Take for instance a template that creates a re-usable callout box that is included on multiple pages throughout a site.  The actual published rendition of this template would not be a full page, but instead just an html fragment.  This fragment, if viewed directly on the website, would probably look pretty strange without the page that holds it.  In these cases, a separate and distinct preview rendition can be created.  This rendition &#8211; while not actually published to the web site &#8211; can show the page snippet in a &#8220;mocked up&#8221; site context.  Seeing the fragment in the correct positioning on a page with the correct styles applied goes a long way to instilling confidence in the user that they have in fact created their content correctly &#8211; once again, improving the usability of the CMS.</p>
<div align="center">
        <img src="/article-assets/images/preview_format.jpg" border="0" alt="Fig. 2: Preview Format">
<p class="figure">
            <b><br />
              Figure 2:<br />
            </b> Sample use of the Preview format</p>
</p></div>
<h4>XML Applications for Metadata Synchronization</h4>
<p>XML Applications are certainly not a new feature of Web Publisher, so I have never understood why they are so infrequently utilized.  XML Applications at their heart are simple XML documents (though there is a little XML App configuration tool &#8211; which in itself could use a lot of work in the usability department &#8211; that developers can use to create and modify them) that when applied to a content template can be used to synchronize metadata to content template fields.  Why might one use these?  Well, let&#8217;s take the simplest example of a page element (and one that affects nearly every web page in your repository) &#8211; the page title.  Every time a user creates a new page, after selecting their template they are immediately launched into the content attributes screen where (after entering the name of their file) they enter the Title for the page.  They check edit now (or have it pre-checked if you have taken my suggestion above), click OK, and the template editor is launched.  What is the first field at the top of the template editor for them to fill out &#8211; you guessed it, Page Title!  Having JUST entered this information on the previous screen, without an XML Application in place, they now have to enter this information again!  Also consider three months down the road when that page title needs to change &#8211; now the user has to make sure to remember to update it in two places instead of just one.  While this is certainly doable, the experience does leave something to be desired.</p>
<p>A simple XML Application configured for two-way synchronization of the content&#8217;s Title attribute with the template&#8217;s Page Title field eliminates this need for double work.  Now the experience is that after the user fills out the Title on the attributes page and launches the template editor, the Page Title comes pre-filled!  If they make a change to this field in the template editor, the change is also reflected in the metadata &#8211; pretty slick.  Keep in mind that while this is a simple usability enhancement for the page title, it can (and should) become an integral part of template design when you start to think about content that is reused dynamically on other pages.  Take for example a product page &#8211; users may specify when creating the content a title, short description, and perhaps even a thumbnail image for the product that is then displayed dynamically on a product listing page.  While annoying, without an XML Application, the title could certainly be entered independently in both the metadata and the page content.  And perhaps the same would hold true for the short description &#8211; but what about the thumbnail image?  While there are great widgets available in the template editor for selecting an image, there really isn&#8217;t a corresponding concept for the attributes page.  Without this synchronization, users would have to manually (and correctly) type out the path to the image they wanted to include.  Add a simple XML App and voila, users can simply pick this image when filling out their content template, and it will automatically show up in the metadata &#8211; no tricky error prone user experience required.</p>
<h3>
        <a name="head5" class="section">Reduce Content Author Decisions</a><br />
    </h3>
<p>Part of the benefit of a powerful content management system like the one Documentum provides is that it allows developers to customize and extend the core framework to meet a particular organization&#8217;s needs.  These customizations can build proprietary business logic right into the system, really tailoring the tool to fit the business.  Unfortunately, with Web Publisher, these sorts of customizations often require a deep level of technical Documentum expertise to implement that many organizations simply don&#8217;t have in house.</p>
<p>Here at Blue Fish, we have been growing our Documentum expertise for years, and so we feel very comfortable making these sorts of enhancements.  The good news for your organization is that even if you don&#8217;t possess these years of experience, Web Publisher provides some great methods for customization that are closer to configuration that true custom software development.  These strategies can allow an organization to get some business logic coded into the system with minimal investment &#8211; in many cases eliminating the need for an expert content author to make certain decisions by teaching the content management system how something needs to be done and allowing the system to perform the task for them.</p>
<h4>Use Folder Mapping to Place Content in Web Cabinets</h4>
<p>One very powerful concept that is built into Web Publisher is that of folder mapping.  The thought underlying folder mapping is that all pages within the content management system should have a &#8220;correct&#8221; place where they live in the folder structure.  Content shouldn&#8217;t be organized haphazardly (like it often is in homegrown systems that have taken on a life of their own after years left to their own devices) &#8211; but should instead consist of a logical structure based on the content and the rules of the business.  Web Publisher&#8217;s folder mapping capability allows a developer to define these business rules of where content should be placed by simply enhancing the rudimentary folder mapping script that is provided out of the box.  By having the system place folders in the correct spot, you know that content is always filed away correctly &#8211; authors don&#8217;t have to remember where content needs to be put, and administrators don&#8217;t have to come along behind them to pick things up that have been put in the wrong place.</p>
<div class="callout">
<p>
            <b></b>
        </p>
<p>Bonus Tip:  Since the folder structure is what is actually published out to the file system for the rendered website, these folders are what actually comprise the URL path on the rendered website &#8211; or what SHOULD comprise the URL in a well designed system.  For example, if the URL for your site looked something like: http://www.emc.com/products/category/content-management.htm, then the &#8220;content-management.htm&#8221; page should probably live in the &#8220;/products/category&#8221; folder within the repository.  Time and time again we see implementations where the importance of this simple design consideration was overlooked and this mapping does not hold true.  The biggest drawback is that this often makes the Webview functionality unusable.  I&#8217;ve already mentioned the importance of webviewing to the content authoring experience, so designing a system that precludes this functionality from working is NOT something that should be taken lightly.  If you are taking the time to design the folder structure, make sure the folders really do mirror the URL structure so that Webview works as designed &#8211; trust me, your content authors will thank you.</p>
</p></div>
<h4>Assign Workflow Based Upon the Content</h4>
<p>I&#8217;ve mentioned that Web Publisher comes with a few sample workflows &#8211; and we&#8217;ve already discussed a simple customization to have Web Publisher automatically launch a workflow if there is only one available to a given user.  The usability enhancements with workflow don&#8217;t have to end there, however!  Nearly every organization I have worked with has some business rule surrounding who should be the approver for a given piece of content.  It may be that all product pages go to the product marketing team, or all press releases go to corporate communications &#8211; or perhaps it is even simpler and all pages go to the same group of approvers.  Whatever the case, there is nearly always some business rule that defines the &#8220;correct approver&#8221; for a given piece of content &#8211; and I always like to say, if you can articulate the business rule, you can code it.  In a well designed content management system, the CMS should know quite a bit about that piece of content that you are launching on a workflow &#8211; enough that is should be able to determine the proper approver of the content for you.  If this business logic can be coded into the workflow, then instead of users having to select the approver (and risk them selecting the wrong one, causing the workflow to be re-routed, and introducing inevitable delays in getting the content out to the web site) the system can automatically route it to the correct person (or even better, group of persons).  One less decision for the content authors to make, one more way the system usability is improved.</p>
<h3>
        <a name="head6" class="section">Conclusion</a><br />
    </h3>
<p>While Documentum is making a huge investment in improving the content authoring experience, your organization doesn&#8217;t need to wait for the next release of Web Publisher to improve usability.   With a little forethought and some graceful design tweaks, even today Web Publisher provides the basis for a powerful (and highly usable) web content management solution.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/web-publisher-usability/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Introduction to the WDK Automated Test Framework</title>
		<link>http://www.bluefishgroup.com/2008/wdk-test-framework/</link>
		<comments>http://www.bluefishgroup.com/2008/wdk-test-framework/#comments</comments>
		<pubDate>Wed, 27 Aug 2008 11:00:00 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Custom ECM Solutions]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=360</guid>
		<description><![CDATA[Introduction The WDK Automated Test Framework was originally created by Documentum for internal testing of WDK components and WDK applications. Although the framework is not an officially supported EMC product, it is made available to partners and developers via the EMC Developer Network (EDN). The WDK Automated Test Framework is available in two versions: Version [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Introduction</a><br />
    </h3>
<p>
The WDK Automated Test Framework was originally created by Documentum for internal testing of WDK components and WDK applications. Although the framework is not an officially supported EMC product, it is made available to partners and developers via the<br />
EMC Developer Network (EDN).<br />
The WDK Automated Test Framework is available in two versions:</p>
<ul>
<li>Version 1.0 is compatible with WDK 5.3 SP5 (or later service packs)</li>
<li>Version 2.0 is compatible with WDK 6.0.</li>
</ul>
<p>
The test framework includes a web-based user interface which allows you to create new tests by recording actions in your custom Webtop or WDK application. The framework is tightly integrated into WDK and runs on any supported WDK browser. It records WDK mouse selection, keyboard shortcuts, right-click menu actions, and supports UCF transfers for importing, viewing, or versioning documents. The user interface allows you to playback recorded tests and verify the behavior of your application without requiring any command-line interactions or editing any configuration files.
</p>
<h3>
        <a name="head2" class="section">Setting up the Framework</a><br />
    </h3>
<p>
The testing framework works with any Webtop or WDK application, but requires that you deploy your application as an unpacked webapp directory, rather than a single WAR file. The unpacked directory is necessary because new tests will be saved as XML and Java files inside the webapp directory. Login to your application and verify that everything is working correctly before you move on.
</p>
<div class="callout">
<p>
            <b></b>
        </p>
<p>
            <em>Note:</em><br />
For clarity, this article bases all examples on an environment consisting of Webtop 6.0 running on Tomcat version 5.5.
</p>
</p></div>
<p>
Download the correct version of the WDK Automated Test Framework from EDN; version 2.0 of the framework is required for Webtop 6.0. Unpack the test framework files into the directory which contains your webapp. The test framework only adds new files, so you should not need to overwrite any existing files. Unpacking the archive is the only step necessary to setup the test framework for testing a standard version Webtop that does not utilize any custom WDK controls.
</p>
<p>
Once this archive is unpacked, you may access the WDK Automated Test Framework UI at:<br />
</p>
<p>&nbsp; &nbsp; <b>http://{host}:{port} /{webapp}/component/testtool</b><br />
        </p>
<p>where {webapp} is the name of the deployed Webtop or WDK application. For example, if you are testing a Webtop instance running on port 8080 of your local machine, then you would point your web browser at:<br />
</p>
<p>&nbsp; &nbsp; <b>http://localhost:8080/webtop/component/testtool</b>
    </p>
<p>
Now that you have verified that the test framework has been correctly deployed, it is time to specify the parameters for recording test cases.
</p>
<h3>
        <a name="head3" class="section">Configuring Recording Parameters</a><br />
    </h3>
<p>
The WDK Automated Test Framework UI generates two artifacts for each recording: an XML configuration file and a Java class. The auto-generated Java class extends com.documentum.web.test.ComponentTestCase and defines a sequence of actions to perform. The XML configuration file is created inside the webapp directory structure under /config/testcase/ and defines values that are used to automatically navigate the WDK application and to verify expected values.
</p>
<p>
To get started, click the [Test Recorder Launcher] link at the top of the main test framework page to access the Recorder Launcher, and then update the settings which will be used to record your new test case.
 </p>
<p><div align="center">
            <img src="/article-assets/images/wdktest/rec001c.gif" border="0" alt="Fig. 1">
<p class="figure">
                <b><br />
              Figure 1:<br />
            </b> The Test Recorder Launcher</p>
</p></div>
</p>
<p><div align="center">
            <img src="/article-assets/images/wdktest/rec002c.gif" border="0" alt="Fig. 2">
<p class="figure">
                <b><br />
              Figure 2:<br />
            </b> Test Recorder Configruation Settings</p>
</p></div>
</p>
<ol>
<li>
The most important elements to be configured are the names and locations of the new XML configuration file and the associated Java class. The &ldquo;classname&rdquo; is the name of the new Java class file and &ldquo;testcaseiId&rdquo; is the name of the new XML configuration file.
</li>
<li>
The &ldquo;packagename&rdquo; value indicates what Java package will be declared in the new auto-generated Java class. The &ldquo;path&rdquo; value is a directory inside the webapp directory structure and should match the &ldquo;packagename&rdquo;.
</li>
<li>
The &ldquo;configpath&rdquo; is the full directory path of the XML configuration file which will be created by the Test Recorder.
</li>
<li>
The &ldquo;URL&rdquo; setting controls the starting URL for the test case. By default this will be the root WebTop component, but it is possible to choose a specific component, for example &ldquo;/component/search&rdquo;.
</li>
<li>
Set &ldquo;auto login&rdquo; to &ldquo;Yes&rdquo; and enter valid &ldquo;user&rdquo;, &ldquo;password&rdquo;, and &ldquo;docbase&rdquo; login information. Your session is automatically logged in using this information, these values will not be recorded in the test case, and you can specify a different login when you playback the test.
</li>
<li>
The &ldquo;clientDataFolderPath&rdquo; specifies a directory on your local machine which contains files used during testing, for example a sample document to be imported.
</li>
</ol>
<p>
Now that you&rsquo;ve successfully set up the testing framework, it is time to record a test.
</p>
<h3>
        <a name="head4" class="section">Recording a Test</a><br />
    </h3>
<p>
A simple Webtop test has three stages:</p>
<ol>
<li>Start Recording</li>
<li>Perform Validation</li>
<li>Finish Recording</li>
</ol>
<div class="callout">
<p>
            <b></b>
        </p>
<p>
The test framework Test Recorder augments the WDK interface to show the webapp being tested in the center of the web page with some special links at the top and bottom. These new links allow you to manage the recording process.
</p>
</p></div>
<h4>1. Start Recording</h4>
<p>
Click the [Record] button located in the bottom right corner of the Test Recorder Launcher to start recording your test. A Recorder Monitor window will be opened and you will immediately be prompted to click [OK] in order to start recording your test actions.
</p>
<p><div align="center">
            <img src="/article-assets/images/wdktest/rec003.gif" border="0" alt="Fig. 3">
<p class="figure">
                <b><br />
              Figure 3:<br />
            </b> Click [OK] to start recording</p>
</p></div>
</p>
<p>
For this introductory example, we will record the steps to perform an import and then modify an attribute. Follow these steps to record your test:</p>
<ul>
<li>
Navigate into a temporary folder and import a sample document. Note that the standard Webtop UCF client is utilized for the import.
</li>
<li>
Use Webtop to view the properties of the imported document, assign a new value to the subject attribute, and save the changes.
</li>
</ul>
<p><div align="center">
            <img src="/article-assets/images/wdktest/rec005c.gif" border="0" alt="Fig. 4">
<p class="figure">
                <b><br />
              Figure 4:<br />
            </b> Import a test document</p>
</p></div>
</p>
<p><div align="center">
            <img src="/article-assets/images/wdktest/rec006c.gif" border="0" alt="Fig. 5">
<p class="figure">
                <b><br />
              Figure 5:<br />
            </b> Modify the Subject Attribute</p>
</p></div>
</p>
<p>
This sample document is now ready to be validated in the next stage of our test.
</p>
<h4>2. Perform Validation</h4>
<p>
An important part of testing is validating that the correct data is displayed to the user. To validate that the test document has the correct attribute value assigned, open the standard Webtop properties viewer and click the &ldquo;Turn On Inspection Mode&rdquo; link (located in the bottom right corner of the Recorder Monitor).
</p>
<p><div align="center">
            <img src="/article-assets/images/wdktest/rec007c.gif" border="0" alt="Fig. 6">
<p class="figure">
                <b><br />
              Figure 6:<br />
            </b> Click &#8211; Turn On Inspection Mode</p>
</p></div>
</p>
<p>
Inspection mode allows you to inspect the values of any WDK component shown by the webapp and record a comparison-check of these values as part of your test. The test will fail if a different value is encountered during playback. When inspection mode is active, a red box is shown as you move the mouse pointer over elements on the properties page. Continuing our example, click the &ldquo;Subject&rdquo; attribute field to open a validation box and perform a comparison against the current value.
</p>
<p><div align="center">
            <img src="/article-assets/images/wdktest/rec008c.gif" border="0" alt="Fig. 7">
<p class="figure">
                <b><br />
              Figure 7:<br />
            </b> Select the &#8220;Subject&#8221; attribute for inspection</p>
</p></div>
</p>
<p><div align="center">
            <img src="/article-assets/images/wdktest/rec009c.gif" border="0" alt="Fig. 8">
<p class="figure">
                <b><br />
              Figure 8:<br />
            </b> Dialog when inspecting the &#8220;Subject&#8221; attribute</p>
</p></div>
</p>
<p>
You may stop inspection mode by clicking the &ldquo;Turn Off Inspection Mode&rdquo; link in the bottom right corner. Close the property inspector and return to the folder browser in Webtop.
</p>
<p><div align="center">
            <img src="/article-assets/images/wdktest/rec010c.gif" border="0" alt="Fig. 9">
<p class="figure">
                <b><br />
              Figure 9:<br />
            </b> Click &#8211; Turn Off Inspection Mode</p>
</p></div>
</p>
<p>
Let&rsquo;s validate that the correct version label is displayed in the document list. To do this, enable inspection mode when the document list is displayed:
</p>
<p><div align="center">
            <img src="/article-assets/images/wdktest/rec011c.gif" border="0" alt="Fig. 10">
<p class="figure">
                <b><br />
              Figure 10:<br />
            </b> Select the version label for validation</p>
</p></div>
</p>
<p><div align="center">
            <img src="/article-assets/images/wdktest/rec012c.gif" border="0" alt="Fig. 11">
<p class="figure">
                <b><br />
              Figure 11:<br />
            </b> Validate the current version label</p>
</p></div>
</p>
<p>
As before, click [OK] to record your validation values and click &ldquo;Turn Off Inspection Mode&rdquo; to end inspection mode.
</p>
<h4>3. Finish Recording</h4>
<p>
Now that we&rsquo;ve performed a few validation tests, let&rsquo;s clean up the content repository. Using Webtop, delete the test document you previously created and then click the &ldquo;Stop Recording&rdquo; link in the bottom right corner of the Recorder Monitor. This ends your test recording. Now click the [Compile] link to compile and hot-deploy the Java class associated with your new test. Close both the &ldquo;Compilation&rdquo; and &ldquo;Recorder Monitor&rdquo; windows to get back to the main test framework UI.
</p>
<p><div align="center">
            <img src="/article-assets/images/wdktest/rec014c.gif" border="0" alt="Fig. 12">
<p class="figure">
                <b><br />
              Figure 12:<br />
            </b> After recording is is finished</p>
</p></div>
</p>
<p><div align="center">
            <img src="/article-assets/images/wdktest/rec015c.gif" border="0" alt="Fig. 13">
<p class="figure">
                <b><br />
              Figure 13:<br />
            </b> Compile the Java class for your test</p>
</p></div>
</p>
<h3>
        <a name="head5" class="section">Executing the Test</a><br />
    </h3>
<p>
New let&rsquo;s execute the test we just recorded. Note that new tests are not immediately visible for playback. To run a recently recorded test you must click the [Refresh ConfigService] button in the bottom left corner of the Test Launcher and then switch to view by &ldquo;testcase&rdquo;.
</p>
<p><div align="center">
            <img src="/article-assets/images/wdktest/play000c.gif" border="0" alt="Fig. 14">
<p class="figure">
                <b><br />
              Figure 14:<br />
            </b> Click [Refresh ConfigService]</p>
</p></div>
</p>
<p><div align="center">
            <img src="/article-assets/images/wdktest/play001c.gif" border="0" alt="Fig. 15">
<p class="figure">
                <b><br />
              Figure 15:<br />
            </b> Select View By: testcase</p>
</p></div>
</p>
<p>
Select the new test in left side tree and then click the right-arrow button to add the test to the current Test Plan. Set &ldquo;auto login&rdquo; to &ldquo;Yes&rdquo; and enter appropriate authentication information.
</p>
<p><div align="center">
            <img src="/article-assets/images/wdktest/play003c2.gif" border="0" alt="Fig. 16">
<p class="figure">
                <b><br />
              Figure 16:<br />
            </b> Add a test to execute</p>
</p></div>
</p>
<p><div align="center">
            <img src="/article-assets/images/wdktest/play004c.gif" border="0" alt="Fig. 17">
<p class="figure">
                <b><br />
              Figure 17:<br />
            </b> Enter authentication information</p>
</p></div>
</p>
<p>
Click the [Launch] button to start playback. After playback finishes, the test results viewer shows success or failure for each test, along with timing information. You can click on individual tests to view more information, which is particularly helpful for finding out why a test failed.
</p>
<p><div align="center">
            <img src="/article-assets/images/wdktest/add03c.gif" border="0" alt="Fig. 18">
<p class="figure">
                <b><br />
              Figure 18:<br />
            </b> Monitor playback, in progress</p>
</p></div>
</p>
<p><div align="center">
            <img src="/article-assets/images/wdktest/add002c.gif" border="0" alt="Fig. 19">
<p class="figure">
                <b><br />
              Figure 19:<br />
            </b> Results, after playback</p>
</p></div>
</p>
<p><div align="center">
            <img src="/article-assets/images/wdktest/add004c.gif" border="0" alt="Fig. 20">
<p class="figure">
                <b><br />
              Figure 20:<br />
            </b> Details of an executed test case</p>
</p></div>
</p>
<h3>
        <a name="head6" class="section">Tips &amp; Tricks</a><br />
    </h3>
<p>
        <b>Use the [Save State] button to record custom settings.</b><br />
        </p>
<p>The settings in the Test Recorder Launcher will be reset to default values when the webapp server is restarted or your browser session ends. The [Save State] button saves the current configuration values out to a file, and you may reload these values anytime using the [Load State] button. Once you establish the recording configuration appropriate for your environment, be sure to save the state. This enables you to quickly reload it later when you want to record a new test case.
</p>
<p>
        <b>The test recorder can be finicky.</b><br />
        </p>
<p>Plan out the sequence of actions before you start recording and keep your tests straightforward. You can break one large test into a series of smaller tests and play them back in sequence using a custom testsuite. It will be easier to re-record individual sections of a large test when necessary rather than the entire test.
</p>
<p>
        <b>Pay attention to which version of Webtop is supported.</b><br />
        </p>
<p>For example, version 2.0 of the WDK Automated Test Framework (Build Number: 6.0.0.089) only indicates support for Webtop 6.0. We have experienced intermittent errors when using Webtop 6.0 SP1, and these errors were resolved by switching to Webtop 6.0 with no service pack.
</p>
<p>
        <b>Avoid reusing testcase names.</b><br />
        </p>
<p>Although the test framework supports hot-deploy of Java classes, updating an existing test can cause Tomcat to throw an exception or otherwise fail to reload the Webtop application. You may need to restart Tomcat, and Tomcat could end up in an invalid state which requires you to manually empty the Tomcat work directory. If you simply append a new version number to any test that is re-recorded, you can avoid issues caused by hot-deployment of existing Java class files.
</p>
<p>
        <b>The recorder may include unintended comparisons.</b><br />
        </p>
<p>This issue may require new tests to be manually tweaked before they will playback correctly. For example, we have seen the recorder unexpectedly check for a specific value of the r_access_date attribute. This works fine when the test is first recorded, but fails each time the test is played back. To remove these unintended validations, you must edit the XML configuration file and remove the fragments related to the fields that should not be validated (r_access_date in the above example). Because of the way the auto-generated Java classes are structured, it may even be necessary to modify the Java class in order to remove the validation step. Straightforward tests are less likely to include unintended comparisons.
</p>
<p>
        <b>Do not leave the test framework on a production system.</b><br />
        </p>
<p>The test framework allows you edit and hot-deploy Java classes without providing authentication information, which poses a security risk. Make sure you update your deployment process so that you can easily deploy without the framework files or delete all files and directories associated with the test framework after deployment. The WDK Automated Test Framework User Guide provides details on which files must be deleted, as well as an ANT snippet for packaging a WAR file which excludes all of the test framework files.
</p>
<h3>
        <a name="head7" class="section">Advanced Usage</a><br />
    </h3>
<p>
Once you understand how to create and playback a basic test, you may want to move on to more advanced test cases. Here is an overview of the test framework&rsquo;s more advanced features:
</p>
<h4>Setup and TearDown</h4>
<p>
When recording a new testcase, you can designate tests to be run as a setup or teardown step. As with standard JUnit-based Java test cases, the setup is performed before executing your test and the teardown is performed after the test execution completes. This allows you to encapsulate common setup or teardown behaviors into a special test which can be reused in new tests.
</p>
<p><div align="center">
            <img src="/article-assets/images/wdktest/adv001c.gif" border="0" alt="Fig. 21">
<p class="figure">
                <b><br />
              Figure 21:<br />
            </b> Specify Setup and TearDown tests</p>
</p></div>
</p>
<h4>Variables</h4>
<p>
You can define input and output variables which will be passed between tests at runtime. For example, you might specify a variable that holds the r_object_id of a test document so that it can be deleted by a teardown test. When sequencing tests together, the output variables from one test are automatically passed into the next test as input variables. You can specify default values which may be overridden when tests are launched in the UI. Managing variables does add complexity, but it also provides flexibility for creating advanced tests.
</p>
<h4>Modify a Test Case</h4>
<p>
Once you have created a useful test, you may want to integrate the java and configuration XML file into your build process. The compiled class may be deployed inside of a jar file, rather than hot-deployed from the source code. The com.documentum.web.test package is provided by the standard webtop.jar, so no additional libraries are required to compile the web test classes. The variable names can also be cleaned up so that it&rsquo;s easier to re-use tests.
</p>
<h4>Custom WDK controls</h4>
<p>
If your application uses custom controls, then you may need to customize the testing framework in order to record tests. The WDK Automated Test Framework Development Guide provides details on how to instrument the test framework to handle custom events and to inspect custom controls. If you do not provide support for a custom control, the test recorder includes an &#8220;unknown control&#8221; comment message in the generated java test class.
</p>
<h4>Tracing</h4>
<p>
If you are already familiar with WDK trace flags, then you may be interested to know that the test framework introduces three new flags for tracing:</p>
<ul>
<li>
com.documentum.web.test.Trace.TESTRECORDER<br />
</p>
<p>This flag traces the recording and production of a test case.
</li>
<li>
com.documentum.web.test.Trace.TESTCASE<br />
</p>
<p>This flag traces the traversal of test suites and test cases and the execution of test cases.
</li>
<li>
com.documentum.web.test.Trace.TESTSTEP<br />
</p>
<p>This flag traces the traversal of test steps and the execution of test steps.
</li>
</ul>
<p>
I encourage you to visit the EMC Developer Network (EDN) for the latest version of the WDK Automated Test Framework and to access the developer forums.
</p>
<h3>
        <a name="head8" class="section">Conclusion</a><br />
    </h3>
<p>
The WDK test framework provides a robust, reproducible mechanism for performing automated end-to-end WDK testing. Because value inspections can be performed on any WDK control, you can test any functionality<br />
invoked &ndash; directly or indirectly &ndash; from the UI,<br />
including complex Documentum functionality such as lifecycle state transitions and custom TBO behaviors. Although custom WDK components require additional customization of the test framework, the many benefits of automated WDK testing should easily make up for the additional effort.
</p>
<h3>
        <a name="head9" class="section">Other Resources</a><br />
    </h3>
<ul>
<li>
                <a target="_blank" href="http://community.emc.com/community/edn">EMC Developer Network (EDN)</a> &#8211; Documentum developer community</li>
<li>
                <a target="_blank" href="http://community.emc.com/docs/DOC-1252">WDK Automated Test Framework</a> &#8211; Download the framework</li>
</ul>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/wdk-test-framework/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Automate BOF Module Deployment During Development</title>
		<link>http://www.bluefishgroup.com/2008/bof-ant-task/</link>
		<comments>http://www.bluefishgroup.com/2008/bof-ant-task/#comments</comments>
		<pubDate>Wed, 06 Aug 2008 11:00:00 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Custom ECM Solutions]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=359</guid>
		<description><![CDATA[Introduction One of the key requirements of any agile development methodology is continuous integrations. In the 9 years I&#8217;ve been writing software professionally, I&#8217;ve noticed a dramatic difference in the overall quality of software produced by projects that employed fully automated continuous integrations over projects that didn&#8217;t. When combined with a full suite of automated [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Introduction</a><br />
    </h3>
<p>
		    One of the key requirements of any agile development methodology is<br />
    		<a target="_blank" href="http://martinfowler.com/articles/continuousIntegration.html">continuous integrations</a>.<br />
    		In the 9 years I&#8217;ve been writing software professionally, I&#8217;ve noticed a dramatic difference in the overall<br />
    		quality of software produced by projects that employed fully automated continuous integrations over projects<br />
    		that didn&#8217;t. When combined with a full suite of automated integration tests, the benefits of continuous integrations are:
		</p>
<ul>
<li>Immediate detection of broken or incompatible code changes.</li>
<li>Immediate unit and integration testing of all changes.</li>
<li>Constant availability of a &#8220;current&#8221; build for testing, demo, and release purposes.</li>
<li>Increased efficiency, predictability, and quality of project development cycles.</li>
</ul>
<p>
		    For releases of Documentum prior to Documentum 6 service pack 1 (D6 sp1), EMC&#8217;s only officially<br />
		    supported mechanism for creating Documentum Business Object Framework modules  (BOFs) is through<br />
		    the Documentum Application Builder (DAB) application, and the only supported mechanism for<br />
		    installing the DocApp archives generated by DAB is through Documentum Application Installer (DAI).<br />
		    As of D6 sp1, EMC is shipping a new application, Documentum Composer, that can be used to install<br />
		    and update BOFs. Of these applications, only Documentum Composer can be executed through a<br />
		    command-line interface, and none support installing or updating BOFs directly from their Java<br />
		    archive (JAR) files &#8211; you must somehow get the BOF into a repository before you can then create<br />
		    an archive of the BOF to install into another repository.  The net result of this is that there<br />
		    are no officially supported mechanisms for creating, updating, and/or deploying BOF modules in a<br />
		    fully automated manner from source code to a target repository.
		</p>
<p>
            Thankfully, DAB ships with an Ant task, &#8220;BOFPackaging&#8221;, that we can use to deploy new modules to a<br />
            Documentum repository. With just a basic understanding of both the Apache Ant build tool and the<br />
            representation of a module within a repository, using the &#8220;BOFPackaging&#8221; task is pretty intuitive.<br />
            For your reference, I&#8217;ve included a<br />
            <a href="/article-assets/code/bof_ant_task_samples.zip">sample project</a><br />
            which demonstrates the BOF installation and<br />
            update operations in Ant for Service Based Objects (SBOs), Type Based Objects (TBOs), and simple modules.
		</p>
<h3>
        <a name="head1" class="section">Overview of BOF Object Schema and Folder Structure</a><br />
    </h3>
<p>
		    First I want to provide a brief overview of the structure of BOF modules deployed in a repository.
		</p>
<p>
            As of DFC 5.3, Documentum BOF code is stored in the docbase repository and dynamically loaded by<br />
            DFC as needed by application code. Service Based Objects (SBOs) are hosted in a single &#8220;global&#8221;<br />
            repository, providing the same functionality to multiple repositories, while Type Based Objects<br />
            (TBOs) are hosted and configured in the repository that uses them. Additionally, Documentum introduced<br />
            the concept of a &#8220;simple module&#8221;, which is a unit of executable code stored in the repository.  Like<br />
            TBOs, simple modules are hosted in the repository that uses them.
		</p>
<p>
            To support this new module framework, a few new object types have been introduced: &#8220;dmc_module&#8221;,<br />
            &#8220;dmc_java_library&#8221;, and &#8220;dmc_jar&#8221;. &#8220;dmc_module&#8221; is a subtype of &#8220;dm_folder&#8221; that represents a BOF module.<br />
            Its custom attributes identify the module type, its implementation class, the interfaces it implements,<br />
            and the modules it depends on. Other attributes provide version information, a description of the<br />
            module&#8217;s functionality, the minimum Java VM version the module can run under, and the developer&#8217;s<br />
            contact information.  Please see the Documentum &#8220;Content Server Object Reference Guide&#8221; for a full description<br />
            of the attributes available on the &#8220;dmc_module&#8221; object type.
		</p>
<p>
            A &#8220;dmc_module&#8221; can contain &#8220;dmc_java_library&#8221; objects and &#8220;dmc_jar&#8221; objects. The &#8220;dmc_java_library&#8221; object<br />
            type is also a subtype of &#8220;dm_folder&#8221; and contains &#8220;dmc_jar&#8221; objects. The &#8220;dmc_jar&#8221; object type is a subtype<br />
            of &#8220;dm_document&#8221; and represents Java archive (JAR) files in the repository.
		</p>
<p>
            Every repository has a System cabinet, which contains a top level folder named Modules.
		</p>
<p>
            By convention, modules are installed under this folder according to their type. For example, SBOs are<br />
            installed under &#8220;/System/Modules/SBO&#8221;, and TBOs are installed under &#8220;/System/Modules/TBO&#8221;. For simple<br />
            modules, you can reuse existing or create additional subfolders of &#8220;/System/Modules&#8221; that match your<br />
            module&#8217;s types. For example, if the repository uses Java-based evaluation of validation expressions,<br />
            the associated modules would appear under &#8220;/System/Modules/Validation&#8221;. The hierarchy of folders under<br />
            &#8220;/System/Modules&#8221; is referred to as the repository&#8217;s &#8220;module registry&#8221;, or simply its &#8220;registry&#8221;.
        </p>
<p><div align="center">
            <img src="/article-assets/images/bof_ant_task_modules_folders.png" border="0" alt="Fig. 1: Figure">
<p class="figure">
                <b><br />
              Figure 1:<br />
            </b> Subfolders of Modules representing BOF types.</p>
</p></div>
</p>
<p>
            For more information on the structure of deployed modules, see the &#8220;BOF Infrastructure&#8221; section of the<br />
            Documentum Foundation Classes Development Guide.
		</p>
<h3>
        <a name="head1" class="section">Using the &#8220;BOFPackaging&#8221; Ant Task</a><br />
    </h3>
<p>
            As mentioned previously, Documentum&#8217;s Documentum Application Builder ships with the &#8220;BOFPackaging&#8221;<br />
            Ant task that we can use to deploy or update modules to a repository. After installing Documentum<br />
            Application Builder, you will find the Ant task in the &#8220;DDS.jar&#8221; file under the<br />
            &#8220;[Documentum install dir]Shared&#8221; directory. Simply add the &#8220;DDS.jar&#8221; file to your Ant project&#8217;s<br />
            classpath (&#8220;dctm.classpath&#8221;), and we&#8217;re ready to begin.
		</p>
<p>
            First we&#8217;ll need to register the custom Ant task using Ant&#8217;s taskdef task in an init<br />
            target so that we can use it within our Ant script.</p>
<pre>
            <code>

&lt;target name="init" &gt;            
	&lt;taskdef name="BOFPackaging"
		classname="com.documentum.bof.ant.BOFPackaging"
        classpathref="dctm.classpath" /&gt;            
&lt;/target&gt;

</code>
        </pre>
<p>            Next we&#8217;ll need to create a new Ant target and leverage the &#8220;BOFPackaging&#8221; task to install<br />
            our custom module, which in this example will be a TBO. I&#8217;ve included sample SBOs and simple<br />
            IDfModules in this article&#8217;s sample project as well.</p>
<pre>
            <code>

&lt;!-- install TBO --&gt;
&lt;target name="install-tbo" depends="init" description="Installs the document TBO to repository"&gt;            
	&lt;BOFPackaging contactInfo="steve@bluefishgroup.com"
			description="A Blue Fish document"
			generateWebService="false"
			minVMVersion=""
			moduleName="${tbo.module.name}"
			moduleType="TBO"&gt;
		&lt;primaryClass name="com.bluefishgroup.sample.tbo.impl.CustomDocument" /&gt;
		&lt;addToPackage versionPolicy="minor"&gt;
			&lt;jarFileSet downloadable="true" file="${tbo.int.jar.file}" jarType="interface" /&gt;
			&lt;jarFileSet downloadable="true" file="${tbo.impl.jar.file}" jarType="implementation" /&gt;
			&lt;javaLib name="${tbo.module.name} TBO dependencies" sandbox="false"&gt;
				&lt;jarFileSet minVMVersion="" downloadable="true" jarType="implementation" dir="${lib.dir}"&gt;
					&lt;include name="jdom-1.0b9.jar" /&gt;
				&lt;/jarFileSet&gt;
			&lt;/javaLib&gt;
		&lt;/addToPackage&gt;
	&lt;/BOFPackaging&gt;
&lt;/target&gt;

</code>
        </pre>
<p>            The following table summarizes the important &#8220;BOFPackaging&#8221; task attributes and sub-elements that<br />
            should be modified to install your own module. For the others values, simply follow the templates<br />
            I&#8217;ve provided in the sample project.</p>
<table>
<table>
<tr>
<td><b>Attribute / Element</b></td>
<td><b>TBO</b></td>
<td><b>SBO</b></td>
<td><b>IDfModule</b></td>
</tr>
<tr>
<td>moduleName (attribute)</td>
<td>The TBO&#8217;s object type. For example, bf_document</td>
<td>The SBO&#8217;s fully qualified interface name. For example,<br />
                    com.bluefishgroup.ICustomService</td>
<td>Any unique module name.</td>
</tr>
<tr>
<td>moduleType (attribute)</td>
<td>TBO</td>
<td>SBO</td>
<td>Any appropriate type name. For example, Aspect, Lifecycle, Validation, or &#8220;&#8221; (empty String)</td>
</tr>
<tr>
<td>primaryClass (element)</td>
<td>The implementation class</td>
<td>The implementation class</td>
<td>The implementation class</td>
</tr>
<tr>
<td>jarFileSet (element; jarType=interface)</td>
<td>The jar file which contains the interface classes. (Optional)</td>
<td>The jar file which contains the interface classes.</td>
<td>The jar file which contains the interface classes. (Optional)</td>
</tr>
<tr>
<td>jarFileSet (element; jarType=implementation)</td>
<td>The jar file which contains the implementation classes</td>
<td>The jar file which contains the implementation classes</td>
<td>The jar file which contains the implementation classes</td>
</tr>
<tr>
<td>javaLib (element)</td>
<td>Includes all third party dependencies. (Optional)</td>
<td>Includes all third party dependencies. (Optional)</td>
<td>Includes all third party dependencies. (Optional)</td>
</tr>
</table>
</table>
<p>            The following are screenshots of the resulting module as viewed in Webtop.<br />
            The module itself resides at &#8220;/System/Modules/[module type]/[module name]&#8220;,<br />
            which in this case is &#8220;/System/Modules/TBO/fnd_custom_attr_doc&#8221;. The TBO&#8217;s<br />
            interface and implementation jars are in the module&#8217;s root folder:</p>
<p><div align="center">
            <img src="/article-assets/images/bof_ant_task_tbo_jars.png" border="0" alt="Fig. 2: Figure">
<p class="figure">
                <b><br />
              Figure 2:<br />
            </b> TBO interface and implementation JAR files.</p>
</p></div>
</p>
<p>
            The TBO module&#8217;s dependencies are stored under the Java library folder<br />
            (&#8220;dmc_java_library&#8221;), &#8220;bf_custom_doc TBO dependencies&#8221;.
        </p>
<p><div align="center">
            <img src="/article-assets/images/bof_ant_task_tbo_deps_jars.png" border="0" alt="Fig. 3: Figure">
<p class="figure">
                <b><br />
              Figure 3:<br />
            </b> TBO dependency JAR files.</p>
</p></div>
</p>
<h3>
        <a name="head1" class="section">Conclusion</a><br />
    </h3>
<p>
		    Using the &#8220;BOFPackaging&#8221; Ant task, you can easily automate the installation<br />
		    and update of BOF modules into any repository. This practice will free you<br />
		    from manual BOF updates, removing what is often the single greatest barrier<br />
		    to continuous integrations on Documentum projects and resulting in greater<br />
		    overall efficiency, predictability, and quality of development cycles.
		</p>
<h3>
        <a name="head1" class="section">Further Reading</a><br />
    </h3>
<ul>
<li>
                <a href="/article-assets/code/bof_ant_task_samples.zip">Article source code</a> &#8211; bof_ant_task_samples.zip</li>
<li>
                <a href="/library/2006/practical-guide-to-bof/">A Practical Guide to the Business Object Framework</a>, by Jason Duke</li>
<li>Documentum Foundation Classes (DFC) 5.3 Development Guide: Chapter 3 &#8211; Using the Business Object Framework (BOF)</li>
<li>
                <a target="_blank" href="http://developer.emc.com/developer/articles/deploy_modules_outside_docapp_part1.htm">Deploying Modules Outside of a Docapp</a> (EMC Developer Network) &#8211; open source Ant task requiring Java 1.5.</li>
<li>
                <a target="_blank" href="http://en.wikipedia.org/wiki/Continuous_Integration">Continuous Integration</a> (Wikipedia)</li>
<li>
                <a target="_blank" href="http://martinfowler.com/articles/continuousIntegration.html">Continuous Integration</a>, by Martin Fowler</li>
</ul>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/bof-ant-task/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Using Documentum Lifecycle State Extensions</title>
		<link>http://www.bluefishgroup.com/2008/using-lifecycle-state-extensions/</link>
		<comments>http://www.bluefishgroup.com/2008/using-lifecycle-state-extensions/#comments</comments>
		<pubDate>Wed, 06 Aug 2008 11:00:00 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Custom ECM Solutions]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=357</guid>
		<description><![CDATA[Introduction Documentum Lifecycles provide a way to change a document&#8217;s properties as it progresses through its natural course of &#8220;life&#8221;. For example, when a document is approved, you might want its approval_date attribute to reflect the date of the signoff. Lifecycles can automate this type of action easily. Additionally, lifecycles can call custom code that [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Introduction</a><br />
    </h3>
<p>Documentum Lifecycles provide a way to change a document&#8217;s properties as it progresses<br />
	 through its natural course of &#8220;life&#8221;. For example, when a document is approved, you might<br />
	  want its approval_date attribute to reflect the date of the signoff. Lifecycles can automate<br />
	  this type of action easily. Additionally, lifecycles can call custom code that can perform<br />
	   additional actions, such as sending a notification that the document was approved.</p>
<p>With Documentum version 5.3, EMC introduced a feature called Lifecycle State Extensions<br />
	 that makes certain types of custom lifecycle actions easier to code and support.<br />
	  Prior to this version, any custom lifecycle code you wrote would be filled with<br />
	   hard-coded references and configuration data. But with the addition of<br />
	    Lifecycle State Extensions, Documentum now provides a place in the repository<br />
	     to store that type of configuration data.</p>
<h3>
        <a name="head2" class="section">What are Lifecycle State Extensions?</a><br />
    </h3>
<p>A lifecycle state extension is a special type of Documentum object relationship (dm_relation)<br />
	 that allows developers to associate custom attributes with a specific lifecycle state.<br />
	   State extensions are useful for storing lifecycle state-specific information that is<br />
	    needed by custom lifecycle state transition code.  For example, consider a document<br />
	     approval lifecycle for architectural plans which requires the notification of various<br />
	      government agencies as the document enters different lifecycle states.   The lists<br />
	       of agencies to notify can be stored in state extensions that are associated with<br />
	        the corresponding lifecycle states.  Custom code can then access the agency lists<br />
	         and generate notifications automatically, tag the documents, or perform any other<br />
	          task that can be written in code.</p>
<p>Documentum provides an out-of-the-box state extension object type: dm_state_extension. This<br />
	 object type is intended to be subtyped to add as many custom attributes as are needed to a<br />
	  lifecycle state.  The dm_state_extension object type is a subtype of dm_relation and can<br />
	   therefore be associated with a lifecycle (dm_policy) object via its parent_id attribute.<br />
	     The state extension type&#8217;s state_no attribute associates the extension with a particular<br />
	      state in the lifecycle.  The state extension&#8217;s child_id simply points back to itself,<br />
	       creating a one-way (hanging) relation.  The diagram below shows the lifecycle state<br />
	        extension-related object types.</p>
<div align="center">
        <img src="/article-assets/images/state-extensions/ulse-objects.jpg" border="0" alt="Fig. 1: Object types">
<p class="figure">
            <b><br />
              Figure 1:<br />
            </b> Lifecycle State Extension-Related Object Types and Relationships</p>
</p></div>
<p>For more information on the basics of dm_relation objects and their binding rules,<br />
	 please see the excellent dm_developer article, <a target="_blank" href="http://www.bluefishgroup.com/library/2002/object-relationships/">Object Relationships</a>.</p>
<p>If you&#8217;re considering using lifecycle state extensions to store Documentum users or groups then<br />
	 you may want to check into Documentum alias sets which will likely provide a better solution,<br />
	  especially for defining ACL accessors and workflow participants.  Here&#8217;s another excellent<br />
	   dm_developer article that explains how to use alias sets for these purposes: <a target="_blank" href="http://www.bluefishgroup.com/library/2005/using-alias-sets-part-2/">Using Documentum Alias Sets</a>.</p>
<h3>
        <a name="head3" class="section">Creating a Custom Lifecycle State Extension Subtype</a><br />
    </h3>
<p>The dm_state_extension object type is provided out-of-the-box so that it can be subtyped<br />
	 to add your custom state-specific attributes.  You can create a custom subtype of dm_state_extension<br />
	  by using the Documentum Application Builder (DAB), by executing DQL statements, or if you&#8217;re using D6 by using the<br />
	  new Documentum Composer administrative interface.<br />
	    The first two methods are described below.</p>
<p>The first step is to determine the size and type of the custom attributes you want to add.<br />
	   Then you can create the new object subtype using your method of choice, DAB or DQL.<br />
	     This example shows the creation of a custom subtype that meets the requirements of<br />
	      the fictional architectural document lifecycle described in the introduction.<br />
	        The new subtype in this example, becuse it is intended to extend the QCReview lifecycle state (Quality Control Review),<br />
	         is named qc_lc_extension.  This new object type has two custom attributes:<br />
	         requires_ext_notification (Boolean), and notify_entities (String(128), repeating).</p>
<h4>Creating a Custom State Extension Subtype Using Application Builder</h4>
<ol>
<li>Using Documentum Application Builder, open the existing docapp that will contain the new lifecycle state extension object type (or create a new DocApp).</li>
<li>Select Insert-&gt;Object Type from the main menu.</li>
<li>Type a name for your custom state extension object type in the &#8220;Type name&#8221; box.</li>
<li>Select the supertype, dm_state_extension.</li>
</ol>
<div align="center">
        <img src="/article-assets/images/state-extensions/ulse-subtype.jpg" border="0" alt="Fig. 2: Create subtype">
<p class="figure">
            <b><br />
              Figure 2:<br />
            </b> Creating a custom subtype of dm_state_extension in DAB</p>
</p></div>
<p>Perform the following steps for each custom attribute that you want to add to the new state extension subtype:</p>
<ol>
<li>Select your new custom state extension object type in the left-hand tree view and then select Insert-&gt;Attribute from the main menu.</li>
<li>Enter a name for the new custom attribute.</li>
<li>Select values for data type, length, and whether the attribute is repeating.</li>
</ol>
<div align="center">
        <img src="/article-assets/images/state-extensions/ulse-attribute.jpg" border="0" alt="Fig. 3: Create attribute">
<p class="figure">
            <b><br />
              Figure 3:<br />
            </b> Adding an attribute to the custom state extension type</p>
</p></div>
<p>4.	Finally, close the object type configuration dialogs and check in the new object type.</p>
<p>
        <b>Note:</b> At this point you should restart the content server to refresh the data dictionary cache.</p>
<h4>Creating a Custom State Extension Subtype Using DQL</h4>
<p>An alternate method for creating a new subtype of dm_state_extension is by using the<br />
	 Documentum query language (DQL).   Use a DQL tool like Samson or DA to create your custom<br />
	  state extension object type.   The DQL statement below creates a custom state extension<br />
	   object type named &#8220;qc_lc_extension&#8221;.</p>
<pre>
        <code>
CREATE TYPE qc_lc_extension (
requires_ext_notifications BOOLEAN,
notify_entites CHAR(128) REPEATING)
WITH SUPERTYPE dm_state_extension;
</code>
    </pre>
<p>Note that the above DQL statement is a simplified example that does not configure many<br />
	 of the available options for the object type&#8217;s attributes.  For complete information about<br />
	  creating objects types via DQL, please see the Documentum Content Server DQL Reference,<br />
	   available from EMC.</p>
<h3>
        <a name="head4" class="section">Setting the Lifecycle&#8217;s extension_type Attribute</a><br />
    </h3>
<p>A lifecycle&#8217;s extension_type attribute must first be set to the name of a state extension<br />
	 object type before a state extension of that type can be used.  This lifecycle attribute is<br />
	  not exposed via the DAB client and must be set via DQL, the API, or DFC.  However, DAB is<br />
	   still a useful tool for uninstalling the lifecycle, a task which must be executed prior<br />
	    to setting its extension_type attribute.  A lifecycle can utilize only one state extension<br />
	     object type.  Follow the steps below to set a lifecycle (dm_policy) object&#8217;s<br />
	      extension_type attribute.</p>
<ol>
<li>Uninstall the lifecycle using DAB (click the &#8216;Uninstall&#8217; button).</li>
<li>Use a DQL statement similar to the one shown below to set the lifecycle&#8217;s extension_type attribute to the name of your custom state extension object type:</li>
<pre>
            <code>
UPDATE dm_policy OBJECT SET extension_type = 'qc_lc_extension' WHERE object_name = 'Architectural_Doc_LC';
</code>
        </pre>
<p>		Note that &#8220;qc_lc_extension&#8221; is the name of the custom state extension object type created in section 2 of this article.</p>
<li>Validate and re-install the lifecycle using DAB (click the &#8216;Validate&#8217; and &#8216;Install&#8217; button).</li>
</ol>
<h3>
        <a name="head5" class="section">Creating Instances of a Custom State Extension</a><br />
    </h3>
<p>Once you&#8217;ve created a custom state extension object type, you can create instances of the object<br />
	 type to extend states in a lifecycle.   The section below explains how to configure a state extension&#8217;s<br />
	  attribute values to extend a given lifecycle state.</p>
<p>These are the state extension attributes that must be populated to extend a lifecycle state:</p>
<ul>
<li>
            <b>relation_name</b> &#8211; Set this value to &#8216;BP_STATE_EXTENSION&#8217; for all state extensions.</li>
<li>
            <b>state_no</b> &#8211; Set this value to the index of the lifecycle state that you want to extend.  The index is 0-based (first lifecycle state is index 0).</li>
<li>
            <b>parent_id</b> &#8211; Set this value to the r_object_id of the lifecycle being extended.</li>
<li>
            <b>child_id</b> &#8211; Set this value to the r_object_id of the state extension instance.  The relationship points back to itself.</li>
<li>
            <b>permanent_link</b> &#8211; Set this value to TRUE if you want all future versions of the lifecycle to have the same state extensions.</li>
</ul>
<p>The example DQL statements below show how to create an instance of a custom lifecycle state extension:</p>
<ol>
<li>First create the lifecycle state extension object, populating all of its attributes except for child_id.</li>
<pre>
            <code>
CREATE qc_lc_extension OBJECT
	SET state_no = &lt;index of state to extend&gt;,
	SET parent_id = '&lt;policy_id&gt;',
	SET relation_name = 'BP_STATE_EXTENSION',
	SET permanent_link = TRUE,
 	SET requires_ext_notifications = TRUE,
	APPEND notify_entites = 'Travis County Commissioner',
	APPEND notify_entites = 'Travis County Tax Assessor',
	APPEND notify_entites = 'City of Austin Zoning Board';
</code>
        </pre>
<li>Next update the state extension&#8217;s child id to be its own object id. This is the ID that was returned from the previous CREATE OBJECT query.</li>
<pre>
            <code>
UPDATE qc_lc_extension OBJECT
	SET child_id = '&lt;id of this state extension&gt;'
	WHERE r_object_id = '&lt;id of this state extension&gt;';
</code>
        </pre>
</ol>
<h3>
        <a name="head6" class="section">Accessing State Extension Attribute Values from Custom Lifecycle Code</a><br />
    </h3>
<p>State extensions are useful because they can store custom attribute values.  These values<br />
 	can be easily accessed in custom Java DFC code that is called from a lifecycle state transition.<br />
   	This section shows how to use DFC to retrieve the correct state extension for an object entering<br />
    	a particular lifecycle state.</p>
<p>
        <b>Note:</b> For more information on creating custom Java lifecycle modules which can be called from<br />
    	 lifecycle state transitions, see this excellent DM Developer article: <a target="_blank" href="http://www.bluefishgroup.com/library/2008/custom-java-lifecycle-modules/">Custom Java Lifecycle Modules</a>.</p>
<p>Documentum provides a handy computed lifecycle attribute, _state_extension_obj[[index]], which is<br />
    	 a built-in mechanism for getting a handle to the appropriate state extension for a given lifecycle state.<br />
    	    Computed attributes are read-only and are evaluated by the Content Server at runtime.  When you query<br />
    	     a lifecycle for its _state_extension_obj value for a particular state index, it will return the<br />
    	      object_id of the corresponding state extension object (if one exists).  For example, consider<br />
    	       the following DFC code:</p>
<pre>
        <code>
// Get the lifecycle's computed attribute value
// for the state's extension id
String stateExtensionIdString = lifecycle.getString(
			"_state_extension_obj[" + stateIndex + "]");
</code>
    </pre>
<p>The code above uses the lifecycle&#8217;s getString() method to return the computed attribute value<br />
	 for _state_extension_obj[&lt;state index&gt;].  The return value is a string containing the r_object_id<br />
	  of the corresponding state extension object instance.</p>
<p>The code example below is a custom implementation of the userPostProcessing() lifecycle state-transition method.<br />
 	  It gets the appropriate lifecycle state extension and then accesses the extension&#8217;s<br />
 	   attribute values and logs them out.</p>
<pre>
        <code>
public void userPostProcessing(IDfSysObject obj, String userName, String targetState) throws DfException {
        
   DfLogger.info(this, "Start userPostProcessing(..)", null, null); 
   DfLogger.info(this, "Lifecycle Name = " + obj.getPolicyName(), null, null);        
   DfLogger.info(this, "Target State = " + targetState, null, null);
        
   // Get the lifecycles's object ID from the transitioning object
   IDfId policyId = obj.getPolicyId();
   DfLogger.info(this, "Lifecycle State Name = " + obj.getCurrentStateName(), null, null); 
        
   int stateIndex = obj.getCurrentState();
   DfLogger.info(this, "Lifecycle State Index = " + stateIndex, null, null); 
        
   IDfSession userSession = obj.getSession();
   IDfPersistentObject lifecycle = userSession.getObject(policyId);
        
   // Get the computed attribute value for the state's extension id
   String stateExtensionIdString = lifecycle.getString("_state_extension_obj[" + stateIndex + "]");       
        
   DfLogger.info(this, "Lifecycle State Extension ID = " + stateExtensionIdString, null, null);        
IDfPersistentObject lifecycleExtension = userSession.getObjectByQualification("qc_lc_extension where    r_object_id = '" + stateExtensionIdString + "'");
        
   boolean requiresExternalNotifications = lifecycleExtension.getBoolean("requires_ext_notifications");
   DfLogger.info(this, "Requires External Notifications = " + requiresExternalNotifications, null, null);
        
   // If this object requires external notifications then
   // log out which entities to notify
   if (requiresExternalNotifications == true) {
      int length = lifecycleExtension.getValueCount("notify_entities");
      String thisNotifyEntity;
      for (int i=0; i&lt;length; ++i) {
         thisNotifyEntity = lifecycleExtension.getRepeatingString("notify_entities", i);
         DfLogger.info(this, "Notify Entity [" +  i + "] : " + thisNotifyEntity, null, null);
      }       	
   }          
}
</code>
    </pre>
<p>The output log for the code&#8217;s execution is shown below.</p>
<pre>
        <code>
 Start userPostProcessing(..)
 Lifecycle Name = Test_Lifecycle
 Target State = QCReview
 Lifecycle State Name = QCReview
 Lifecycle State Index = 1
 Lifecycle State Extension ID = 3704a32080000100
 Requires External Notifications = true
 Notify Entity [0] : Travis County Commissioner
 Notify Entity [1] : Travis County Tax Assessor
 Notify Entity [2] : City of Austin Zoning Board
</code>
    </pre>
<p>Notice that the method&#8217;s targetState parameter is the friendly string name for the lifecycle state,<br />
 not the state&#8217;s index which we need in order to get the lifecycle&#8217;s computed state_extension_obj[&lt;i&gt;]<br />
  attribute.   So we instead call the transitioning object&#8217;s obj.getCurrentState() method which returns<br />
   the state&#8217;s integer index.   This works fine because we are in the userPostProcessing(..) method,<br />
    however the table below shows that the object&#8217;s current state may not be what you&#8217;d expect within<br />
     other lifecycle state transitions methods.</p>
<div align="center">
        <img src="/article-assets/images/state-extensions/ulse-current-state.jpg" border="0" alt="Fig. 4: Current states">
<p class="figure">
            <b><br />
              Figure 4:<br />
            </b> Comparison of targetState vs. getCurrentState() values for an object  transitioning into the QCReview lifecycle state</p>
</p></div>
<h3>
        <a name="head7" class="section">Wrap-up</a><br />
    </h3>
<p>Lifecycle state extensions are a little-known feature in Documentum that can be very useful<br />
	 when you need to maintain custom state-specific attribute values for a lifecycle.<br />
	   When you use state extensions in your solutions, remember to thoroughly document<br />
	    their role and maintenance as their presence won&#8217;t be immediately obvious in<br />
	     Documentum&#8217;s out-of-the-box administrative tools and applications.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/using-lifecycle-state-extensions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bullet Proof Markup: Designing for Web Content Management Systems</title>
		<link>http://www.bluefishgroup.com/2008/bullet-proof-markup-designing-for-content-management-systems/</link>
		<comments>http://www.bluefishgroup.com/2008/bullet-proof-markup-designing-for-content-management-systems/#comments</comments>
		<pubDate>Wed, 06 Aug 2008 11:00:00 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Web Content Management]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=358</guid>
		<description><![CDATA[Overview This article will introduce you to some general strategies for writing flexible markup as well as provide some specific examples that you can take away for your next project. First let&#8217;s look at just a few of the modern trends in web design: minimize class usage minimize tag usage semantic markup reusable markup Look [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Overview</a><br />
    </h3>
<p>This article will introduce you to some general strategies for writing flexible markup as well as provide some specific examples that you can take away for your next project. First let&rsquo;s look at just a few of the modern trends in web design:
	    </p>
<ul>
<li>minimize class usage</li>
<li>minimize tag usage</li>
<li>semantic markup</li>
<li>reusable markup</li>
</ul>
<p>
	       Look familiar? The first three trends are certainly accepted and practiced on a regular basis. Reusable markup, however, is often paid lip service but rarely practiced. What I&rsquo;m going to show you is how to take the first three trends and set them aside so that we can achieve the fourth.
        </p>
<p>
           Reusable markup is not appropriate for every project. Semantic markup, minimal tags, and minimal classes are generally a good thing. However, there are times when flexibility and markup reuse are more important.
        </p>
<p>
           Let&rsquo;s look at a few examples where this is the case. When designing for a content management system (CMS), it is especially important to ensure that your markup is both flexible and robust. Many content management systems use a template based architecture for building pages, and therefore your markup must be capable of supporting diverse designs without significant modification.
        </p>
<p>
           Or you may be working in an environment where the HTML cannot be modified, but you have full control of the CSS. In such a situation, it is extremely important that your HTML can accommodate changes. While it&rsquo;s true that no two projects will use the exact same markup, a little forethought can go a long way when reusing code.
       </p>
<h3>
        <a name="head2" class="section">General Strategy</a><br />
    </h3>
<h4>Element ID&#8217;s and Clases</h4>
<p>
           Element ID&rsquo;s differ from classes in a number of ways. First of all, ID&rsquo;s must be unique in an HTML document. Duplicate ID&rsquo;s might appear to work at first glance, but your markup won&rsquo;t validate and you will likely run into problems when working with Javascript and CSS. When you consider some unique components might later be repeated on a page, it&rsquo;s important to choose your ID&rsquo;s carefully.
       </p>
<p>
           Another consideration is that ID&rsquo;s carry more weight (10 to 1 ratio) when measuring CSS specificity. Take the following markup and CSS for example:
       </p>
<pre>
        <code>
&lt;div class="box"&gt;
    &lt;p id="para" class="review"&gt;
    ...
    &lt;/p&gt;
&lt;/div&lt;
</code>
    </pre>
<pre>
        <code>
#para {
    width: 400px;
}
    div.box p.review {
    width: 200px;
}
</code>
    </pre>
<p>
        The first rule (#para) will be honored even though the second rule (div.box p.review) is declared subsequently and contains more selectors. This is because the ID selector counts as 10 points (an ID), while the second rule counts only as a total of 4 points (2 elements and 2 classes). Of course, you could override the ID selector by using the , but such a technique should be used sparingly.
</p>
<p>
        ID&rsquo;s have their place in markup &#8211; they&rsquo;re easier to target with Javascript and sometimes their greater specificity makes sense in CSS. Nevertheless, try to limit ID&rsquo;s to the main page components such as the header, body, aside, and footer. Otherwise, consider using a class just to be safe.
</p>
<h4>Styling Element Selectors</h4>
<p>
        When designers first began taking advantage of CSS, they used classes almost indiscriminately which resulted in markup only marginally preferable to inline style. As techniques progressed, most designers have switched to using as few classes and ID&rsquo;s as possible while targeting child elements using descendent selectors. This is generally the preferred method, but something to be careful of when designing for user generated content. Let&rsquo;s look at the following example which includes a <code>div</code> with a child <code>blockquote</code>:
</p>
<pre>
        <code>
&lt;div id="my-body"&gt;
  &lt;blockquote&gt;
    Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Proin in tellus quis eros imperdiet tempor. Morbi et sem lacinia nisi molestie auctor. Mauris rhoncus augue eu eros. Cras porta dui nec odio.
  &lt;blockquote&gt;
&lt;/div&gt;
</code>
    </pre>
<p>
    It might be tempting to target this using the following:
</p>
<pre>
        <code>
#body blockquote {
  background: #EFEFEF;
  border: 1px solid #CCC;
}
</code>
    </pre>
<p>
        While this works fine and keeps your <code>blockquote</code> element free of a class, this method runs the risk that any user generated content will also receive the same styling which may not be your intent. Even though it&rsquo;s somewhat antithetical to recent markup trends, you might want to be more explicit:
</p>
<pre>
        <code>
&lt;div id="body"&gt;
  &lt;blockquote class="review"&gt;
    Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Proin in tellus quis eros imperdiet tempor. Morbi et sem lacinia nisi molestie auctor. Mauris rhoncus augue eu eros. Cras porta dui nec odio.
  &lt;blockquote&gt;
&lt;/div&gt;
</code>
    </pre>
<pre>
        <code>
#body blockquote.review {
  background: #EFEFEF;
  border: 1px solid #CCC;
}
</code>
    </pre>
<p>
        This ensures that any user generated blockquote will receive generic style, but your review blockquote will receive your intended style.
</p>
<h4>Anticipating User Generated Content</h4>
<p>
         Many sites today deal with user generated content in one way or another. CMS&rsquo;s typically offer rich text editors that offer users the opportunity to add just about any type of content to a page. Whether it&rsquo;s a content management system, a social network, or an e-commerce site, it&rsquo;s a good idea to anticipate the nature of the user generated content that your design must accommodate.
</p>
<p>
        First, a good practice to employ is a CSS &ldquo;reset&rdquo; file. Since different browsers have different default values for HTML elements, it&rsquo;s a good idea to normalize all elements before you apply any specific style. A reset will style all common HTML elements with consistent values. For example, one browser might apply a 1em margin for headings, while another browser might apply 2ems. Using a reset file in this case might set the margin to 0ems for all browsers, giving you a common starting point for your custom style. Without a reset file, you might run into some unexpected inconsistencies between browsers.
</p>
<p>
        Next it&rsquo;s a good idea to set up a base CSS. Your base should create a consistent, simple style that you can use as a starting point for your design. Additionally, this base style can be used for any user generated content which will likely be some type of general rich text. This is why it&rsquo;s important to be careful when styling your element selectors so that you don&rsquo;t unintentionally affect any user generated content.
</p>
<p>
        One final technique you can employ when dealing with such content is to take care of max-widths, word-wraps, and overflows.
</p>
<p>
        Setting a max width in the content area of your site helps to prevent the horizontal dimensions from being pushed beyond their intended boundary. This can happen with large images, unbroken character strings, and user generated inline style. For most modern browsers, you can simply set the max-width in CSS. For example, if your content area is 600 pixels wide div with an id of &ldquo;article&rdquo;, you could do the following:
</p>
<pre>
        <code>
&lt;div id="article"&gt;
  ...
&lt;/div&gt;
</code>
    </pre>
<p>
        And in your CSS declare:
</p>
<pre>
        <code>
#article {
  max-width: 600px;
}
</code>
    </pre>
<p>
        Keep in mind however that this does not work in IE6, so if you are supporting that browser version you&rsquo;ll need to set max-width using external Javascript or with the following Javascript in CSS:
</p>
<pre>
        <code>
#article {
  width: 600px;
  _width: expression(document.body.clientWidth &gt; 601? "600px" : "auto");
}
</code>
    </pre>
<p>
        One nice CSS property found in IE6, IE7, and Safari 3.1 is word-wrap, which was introduced by Microsoft and is now part of the CSS3 working draft. The word-wrap property accepts the value of break-word, which tells the browser to break any text string that reaches the horizontal boundary of its container, and wrap the string to the next line. Taking our &ldquo;article&rdquo; div as an example again, we can declare:
</p>
<pre>
        <code>
#article {
  word-wrap: break-word;
}
</code>
    </pre>
<p>
        Unfortunately this doesn&rsquo;t currently work in Firefox or Opera, but is expected to be supported in Firefox 3.1 and an undetermined future version of Opera. There are some workarounds for Firefox, but they are not trivial to implement and the result is less than ideal. As a defensive measure for the browsers, you can set the overflow-x property to either hidden or scroll depending on the your desired effect. This will at least ensure that your dimensions are respected and any content that is too wide for the div will trigger the overflow according to your design needs.
</p>
<h3>
        <a name="head3" class="section">Examples</a><br />
    </h3>
<p>
        The following examples will work in all modern browsers1. For convenience I have embedded screen captures in this article, however you can <a href="/article-assets/code/bullet-proof-markup/bullet-proof-markup.zip">download the working examples</a> in a separate file.
</p>
<h4>Buttons</h4>
<p>
        One of the most common web site elements is the button. Let&rsquo;s take a look at a plain button element:
    </p>
<pre>
        <code>
&lt;button&gt;Click Me&lt;/button&gt;
</code>
    </pre>
<div align="center">
        <img src="/article-assets/images/bullet-proof-markup/bpm-button.png" border="0" alt="Fig. 1: plain button">
<p class="figure">
            <b><br />
              Figure 1:<br />
            </b> A plain button with no styling.</p>
</p></div>
<p>
    Often a plain button will do just fine, but you might want to match the visual design of the site. Or maybe you just want the button to look consistent across different browsers and operating systems. Let&rsquo;s take a look at the same standard button with some additional styling:
</p>
<pre>
        <code>
&lt;button&gt;Click Me&lt;/button&gt;
</code>
    </pre>
<pre>
        <code>
button {
  background: #EBF4F8;
  border: 1px solid #B6CCD2;
  color: #0671AB;
  padding: .7em;
}
</code>
    </pre>
<div align="center">
        <img src="/article-assets/images/bullet-proof-markup/bpm-button-css.png" border="0" alt="Fig. 2: button with CSS">
<p class="figure">
            <b><br />
              Figure 2:<br />
            </b> A button with CSS style.</p>
</p></div>
<p>
That&rsquo;s better! It has a bit more style and appears consistently across browsers and OS&rsquo;s. But what happens if you don&rsquo;t know what the final design is going to look like, and another developer is waiting on the markup? You could give that developer what you have now, and go through the whole process again if there are any design changes. Or, you could add add a little more markup and allow yourself some design flexibility.
</p>
<p>
    Let&rsquo;s say the client decides they prefer something a bit softer with rounded corners. That&rsquo;s simple enough you think, you can just create a background image and add that to your CSS rule. But that doesn&rsquo;t allow for variable width content &#8211; for that we&rsquo;ll need something extra. The extra markup, or &ldquo;hook&rdquo;, provides an additional element to which we can attach another background image. We&rsquo;ll employ the &ldquo;sliding doors&rdquo; technique and attach one image to our button element and one image to our span element. This will ensure that our button will scale horizontally.
</p>
<pre>
        <code>
&lt;button&gt;&lt;span&gt;Welcome to our Intranet&lt;/span&gt;&lt;/button&gt;
</code>
    </pre>
<pre>
        <code>
button {
  background: url('button-right.png') right center no-repeat;
  border: none;
  color: #0671AB;
  height: 30px;
  margin-right: 7px;
  padding: 0 7px 0 0;
}
button span {
  background: #EBF4F8 url('button-left.png') left center no-repeat;
  display: block;
  line-height: 15px;
  margin: -2px 0 0 0;
  padding: 7px 0 7px 10px;
}
</code>
    </pre>
<div align="center">
        <img src="/article-assets/images/bullet-proof-markup/bpm-button-hooks.png" border="0" alt="Fig. 3: button with hooks">
<p class="figure">
            <b><br />
              Figure 3:<br />
            </b> A buton with markup hooks and background images that scales horizontally.</p>
</p></div>
<p>And now we have a button with rounded corners that scales to any horizontal dimension. By planning ahead and adding your hooks, you can be more certain that future design changes won&rsquo;t require any markup modifications.
</p>
<h4>Lists</h4>
<p>
    Another common website element is the list. First let&rsquo;s take a look at a standard, semantically marked up unordered list of items:
</p>
<pre>
        <code>
&lt;ul&gt;
  &lt;li&gt;Item One&lt;/li&gt;
  &lt;li&gt;Item Two&lt;/li&gt;
  &lt;li&gt;Item Three&lt;/li&gt;
  &lt;li&gt;Item Four&lt;/li&gt;
&lt;/ul&gt;
</code>
    </pre>
<div align="center">
        <img src="/article-assets/images/bullet-proof-markup/bpm-list.png" border="0" alt="Fig. 4: plain list">
<p class="figure">
            <b><br />
              Figure 4:<br />
            </b> A plain unordered list with no styling.</p>
</p></div>
<p>Nice and clean. Now let&rsquo;s add a bit of style. We&rsquo;ll take the same markup and give the whole list a blue background and separate each item with a horizontal line using the following CSS:
</p>
<pre>
        <code>
ul {
  background: #EBF4F8;
  border: 1px solid #B6CCD2;
  color: #0671AB;
  padding: .5em 1em;
  width: 300px;
}
ul li {
  border-bottom: 1px solid #B6CCD2;
  background-image: url('bullet.png');
  background-position: center left;
  background-repeat: no-repeat;
  list-style: none;
  padding: .5em 0 .5em .5em;
}
</code>
    </pre>
<div align="center">
        <img src="/article-assets/images/bullet-proof-markup/bpm-list-css.png" border="0" alt="Fig. 5: list with css">
<p class="figure">
            <b><br />
              Figure 5:<br />
            </b> An unordered list with with CSS style.</p>
</p></div>
<p>That&rsquo;s looking better. But the separator on the last item looks a bit out of place with nothing below it. There are a number of ways we could fix this. We could use Javascript to navigate the DOM and remove the border from the last list item, but that seems a bit heavy-handed. We could add a class called &ldquo;no-border&rdquo; to the last item, but that&rsquo;s not a very semantic name and we may want to do something different in the future that doesn&rsquo;t make sense when called &ldquo;no-border&rdquo;.
</p>
<p>
    Let&rsquo;s examine the common design problem here. Very often a designer will want to style the first or last item in a list differently &#8211; for example, adding or removing a border, changing the background image, etc. Sometimes these changes come late in a projects life cycle, and it may not be so easy to change the markup. To anticipate this, we can add a class called &ldquo;first&rdquo; to the first item in the list, and a class called &ldquo;last&rdquo; to the last item in the list. Let&rsquo;s look at the new markup and CSS to achieve this:
</p>
<pre>
        <code>
&lt;ul&gt;
  &lt;li class="first"&gt;Item One&lt;/li&gt;
  &lt;li&gt;Item Two&lt;/li&gt;
  &lt;li&gt;Item Three&lt;/li&gt;
  &lt;li class="last"&gt;Item Four&lt;/li&gt;
&lt;/ul&gt;
</code>
    </pre>
<pre>
        <code>
ul li {
  border-bottom: 1px solid #B6CCD2;
  background-image: url('bullet.png');
  background-position: center left;
  background-repeat: no-repeat;
  list-style: none;
  padding: .5em 0 .5em .5em;
}
ul li.last {
  border-bottom: none;
}
</code>
    </pre>
<div align="center">
        <img src="/article-assets/images/bullet-proof-markup/bpm-list-css-no-border.png" border="0" alt="Fig. 6: list with class hooks">
<p class="figure">
            <b><br />
              Figure 6:<br />
            </b> An unordered list with classes on the first and last items.</p>
</p></div>
<p>Now, we&rsquo;ve removed the last border. That looks better! While we&rsquo;ve only used the last class in this case, it&rsquo;s a good idea to include both just in case. This first/last method can be used for any type of repeating element on a page and be very convenient when you need to fine tune the design.
</p>
<p>
    We can also apply the technique we learned about buttons to provide additional hooks that we might want for each item. In this case we want two images on each list item &#8211; one for the bullet and one for an arrow on the right. Here is our final markup and visual design:
</p>
<pre>
        <code>
&lt;ul&gt;
  &lt;li class="first"&gt;&lt;span&gt;Item One&lt;/span&gt;&lt;/li&gt;
  &lt;li&gt;&lt;span&gt;Item Two&lt;/span&gt;&lt;/li&gt;
  &lt;li&gt;&lt;span&gt;Item Three&lt;/span&gt;&lt;/li&gt;
  &lt;li class="last"&gt;&lt;span&gt;Item Four&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
</code>
    </pre>
<pre>
        <code>
ul li {
  border-bottom: 1px solid #B6CCD2;
  background-image: url('bullet.png');
  background-position: center left;
  background-repeat: no-repeat;
  list-style: none;
  padding: .5em 0 .5em .5em;
}
ul li.last {
  border-bottom: none;
}
ul li span {
  display: block;
  background: url('list-arrow.png') center right no-repeat;
}
</code>
    </pre>
<div align="center">
        <img src="/article-assets/images/bullet-proof-markup/bpm-list-hooks.png" border="0" alt="Fig. 7: list with markup hooks">
<p class="figure">
            <b><br />
              Figure 7:<br />
            </b> An unordered list with markup hooks for background images.</p>
</p></div>
<h4>Boxes</h4>
<p>Boxes are everywhere in web design. They&rsquo;re used to organize content on the page and highlight information. All modern browsers can handle some level of style without resorting to markup hooks. Let&rsquo;s look at an example box with some text and simple styling:
</p>
<pre>
        <code>
&lt;div&gt;
  &lt;p&gt;
    Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Proin in tellus quis eros imperdiet tempor. Morbi et sem lacinia nisi molestie auctor. Mauris rhoncus augue eu eros. Cras porta dui nec odio. Donec interdum, tellus id volutpat faucibus, mi lacus tempor tortor, eget pellentesque mauris nunc ut ante. Vivamus nec sapien ac lorem volutpat consequat. Quisque dolor. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nullam lacinia erat. Maecenas vestibulum.
  &lt;/p&gt;
&lt;/div&gt;
</code>
    </pre>
<pre>
        <code>
div {
  background: #EBF4F8;
  border: 3px solid #B6CCD2;
  color: #333;
  padding: 1em;
  width: 400px;
}
</code>
    </pre>
<div align="center">
        <img src="/article-assets/images/bullet-proof-markup/bpm-box-css.png" border="0" alt="Fig. 8: box with css">
<p class="figure">
            <b><br />
              Figure 8:<br />
            </b> A box with CSS style.</p>
</p></div>
<p>That looks nice and clean. But once again let&rsquo;s look at the challenge presented by rounded corners, as it&rsquo;s such a common design technique. Just like our button above, we could use a single background image and fix the height and width of the div to match. Unfortunately that doesn&rsquo;t work with dynamic content and therefore is not very flexible. We could create two images &#8211; one for the top half and one for the bottom half, but that doesn&rsquo;t scale horizontally. Let&rsquo;s be sure our box can handle anything and allow it to scale both horizontally and vertically.
</p>
<p>Because a single HTML element can only have one background image attached, we&rsquo;ll need five elements to achieve our box &#8211; one element for the container and one element for each corner. We&rsquo;ll nest them like this:
</p>
<pre>
        <code>
&lt;div&gt;
  &lt;div class="upper-left"&gt;
    &lt;div class="upper-right"&gt;
      &lt;div class="lower-left"&gt;
        &lt;div class="lower-right"&gt;
          &lt;p&gt;
            Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Proin in tellus quis eros imperdiet tempor. Morbi et sem lacinia nisi molestie auctor. Mauris rhoncus augue eu eros. Cras porta dui nec odio. Donec interdum, tellus id volutpat faucibus, mi lacus tempor tortor, eget pellentesque mauris nunc ut ante. Vivamus nec sapien ac lorem volutpat consequat. Quisque dolor. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Nullam lacinia erat. Maecenas vestibulum.
          &lt;/p&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
</code>
    </pre>
<p>
    Now we&rsquo;ll add some CSS to make it all work. Each corner element will have its own background image while the container has a border to make it all appear seamless.
</p>
<pre>
        <code>
div {
  background-color: #EBF4F8;
  border: 3px solid #B6CCD2;
  width: 426px;
}
div .upper-left {
  background: url('box-upper-left.png') left top no-repeat;
  margin: -3px 0 0 -3px;
}
div .upper-right {
  background: url('box-upper-right.png') right top no-repeat;
  margin: 0 -3px 0 0;
}
div .lower-left {
  background: url('box-lower-left.png') left bottom no-repeat;
  margin: 0 0 -3px 0;
}
div .lower-right {
  background: url('box-lower-right.png') right bottom no-repeat;
  margin: 0 0 -3px 0;
  padding: 1em;
}
</code>
    </pre>
<div align="center">
        <img src="/article-assets/images/bullet-proof-markup/bpm-box-hooks.png" border="0" alt="Fig. 9: box with markup hooks">
<p class="figure">
            <b><br />
              Figure 9:<br />
            </b> A box with markup hooks for background images to create rounded corners and scalable dimensions.</p>
</p></div>
<p>
And there is our fully scalable box with rounded corners. It works, but that&rsquo;s a lot of effort just to get rounded corners. And it gets trickier if your box will appear on different backgrounds or if you need a gradient inside the box. There&rsquo;s got to be an easier way, right?
</p>
<h4>Looking Forward</h4>
<p>
Many of the strategies discussed in this article should be useful for years to come. Anticipating user generated content, selecting ID&rsquo;s and classes appropriately, and generally thinking through your entire design are approaches that are not going to disappear. However, recent advances in CSS suggest that many of the markup hooks described above will not be necessary in the coming years. In fact, the current CSS3 working draft obviates the need for all them. Safari 3.1, Firefox 3, and Opera 9.5 all have some level of support for CSS3 and promise more to come. Even Microsoft has begun introducing some CSS3 support in their IE8 beta.
</p>
<p>
Let&rsquo;s take another look at the examples above and see what we can do with a browser that supports some of the CSS3 recommendations.
</p>
<h4>Buttons</h4>
<p>
The new border-radius property allows rounded corners without the need for images or markup hooks. You can use this today with experimental support in Safari 3.1 and Firefox 3.
</p>
<pre>
        <code>
&lt;button&gt;Click Me&lt;/button&gt;
</code>
    </pre>
<pre>
        <code>
button {
  border: 1px solid #B6CCD2;
  background-color: #EBF4F8;
  color: #0671AB;
  padding: .7em;
  -moz-border-radius: 10px;
  -webkit-border-radius: 10px;
}
</code>
    </pre>
<div align="center">
        <img src="/article-assets/images/bullet-proof-markup/bpm-button-css3.png" border="0" alt="Fig. 10: A button with CSS border radius.">
<p class="figure">
            <b><br />
              Figure 10:<br />
            </b> A button with CSS3 border-radius applied.</p>
</p></div>
<h4>Lists</h4>
<p>
If you&rsquo;ll recall in our example above, we had to use markup hooks and extra classes to achieve or design goal. Now let&rsquo;s see what we can do with a plain semantic list.
</p>
<pre>
        <code>
&lt;ul&gt;
  &lt;li&gt;Item One&lt;/li&gt;
  &lt;li&gt;Item Two&lt;/li&gt;
  &lt;li&gt;Item Three&lt;/li&gt;
  &lt;li&gt;Item Four&lt;/li&gt;
&lt;/ul&gt;
</code>
    </pre>
<pre>
        <code>
ul {
  background: #EBF4F8;
  border: 1px solid #B6CCD2;
  color: #0671AB;
  padding: .5em 1em;
  width: 300px;
}
ul li {
  border-bottom: 1px solid #B6CCD2;
  background-image: url('bullet.png'), url('list-arrow.png');
  background-position: left center, right center;
  background-repeat: no-repeat;
  list-style: none;
  padding: .5em 0 .5em .5em;
}
ul li:last-child {
  border: none;
}
</code>
    </pre>
<div align="center">
        <img src="/article-assets/images/bullet-proof-markup/bpm-list-css3.png" border="0" alt="Fig. 11: A list with CSS last-child">
<p class="figure">
            <b><br />
              Figure 11:<br />
            </b> An unordered list with CSS last-child style.</p>
</p></div>
<p>
Looks great, and no extra spans or classes were needed! Using the last-child pseudo element supported by most modern browsers (CSS2), and the multiple background image support of Safari 3.1 (CSS3) we can achieve the same effect.
</p>
<h4>Boxes</h4>
<p>
Now we&rsquo;ll take a look at our last example, the scalable box with rounded corners. Remember all the hooks and images we needed before? Here&rsquo;s the only markup we need if we&rsquo;re using CSS3:
</p>
<pre>
        <code>
&lt;div&gt;
  &lt;p&gt;Phasellus adipiscing iaculis nisl. Phasellus ultricies odio a lacus. Proin sollicitudin adipiscing velit. Donec tempor tortor at elit scelerisque tincidunt. Suspendisse potenti. Donec egestas est ut elit.
  &lt;/p&gt;
&lt;/div&gt;
</code>
    </pre>
<pre>
        <code>
    div {
      background: #EBF4F8;
      border: 3px solid #B6CCD2;
      color: #333;
      padding: 1em;
      width: 400px;
      -moz-border-radius: 10px;
      -webkit-border-radius: 10px;
    }
</code>
    </pre>
<div align="center">
        <img src="/article-assets/images/bullet-proof-markup/bpm-box-css3.png" border="0" alt="Fig. 12: box with CSS3 border-radius">
<p class="figure">
            <b><br />
              Figure 12:<br />
            </b> A box with CSS3 border-radius style.</p>
</p></div>
<p>
Once again we use the experimental border-radius property and our rounded, scalable box is now simple to create.
</p>
<p>
As you can see, it&rsquo;s already possible to eliminate all of the aforementioned hooks with a shipping browser (Safari 3.1). There are other CSS features coming soon that I didn&rsquo;t even touch on in this article such as animations, transformations, variables, and more. It will take some time, but all the major browsers will eventually get there and the users will be sure to follow. Until then, a little extra markup will help you on your way.
</p>
<h4>Conclusion</h4>
<p>
    While the benefits of semantic and minimal markup are great, writing reusable code can be more important in some situations. If you&rsquo;re creating page templates for a CMS or working in an environment where the markup is not always available for modification, you may want to consider adding some extra hooks. The defensive CSS strategies are always good to keep in mind when dealing with user generated content. Whether or not these techniques are appropriate for your next project, is something that you&rsquo;ll have to decide.
</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/bullet-proof-markup-designing-for-content-management-systems/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>What&#8217;s New in Endeca 6.0</title>
		<link>http://www.bluefishgroup.com/2008/whats-new-in-endeca-6/</link>
		<comments>http://www.bluefishgroup.com/2008/whats-new-in-endeca-6/#comments</comments>
		<pubDate>Wed, 23 Jul 2008 11:00:00 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Information Access]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/?p=356</guid>
		<description><![CDATA[Introduction Endeca has thrived by continually updating their flagship search offering, the Information Access Platform, to keep ahead of the game in the arena of world-class search and navigation engines. And the upcoming version 6.0 is no exception. This article will describe some of the most notable enhancements in version 6.0 that you may be [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h4>Introduction</h4>
<p>Endeca has thrived by continually updating their flagship search offering, the Information Access Platform, to keep ahead of the game in the arena of world-class search and navigation engines.  And the upcoming version 6.0 is no exception.</p>
<p>This article will describe some of the most notable enhancements in version 6.0 that you may be interested in if you are currently using a previous version of Endeca&#8217;s Information Access Platform (IAP).  It assumes a basic familiarity with the Endeca concepts and components.</p>
<h4>XQuery</h4>
<p>One of the most fundamental and interesting new pieces of functionality in Endeca IAP 6.0 is the inclusion of an XQuery evaluator in the MDEX Engine.</p>
<p>XQuery (also sometimes called XML Query) is a W3C standard language that is designed to easily query across XML data.  It utilizes the XPath standard that is also used in XSLT, but combines that with a full-featured language syntax to provide extensibility in data processing.  This gives XQuery the ability to perform complex operations on XML data that would have previously required code in other languages leveraging purpose-built libraries for processing XML.  The technical details about XQuery are beyond the scope of this article, but there is a wealth of information about it online. The XQuery 1.0 Specification (<a target="_blank" href="http://www.w3.org/TR/xquery/">http://www.w3.org/TR/xquery/</a>) and this XQuery Tutorial (<a target="_blank" href="http://www.w3schools.com/xquery/">http://www.w3schools.com/xquery/</a>) are good places to start.</p>
<p>Endeca chose to implement an XQuery evaluator as part of its new MDEX engine to provide the ability to write extensible code that is deployed in the engine instead of in the application, and can be bound to web-service interfaces exposed by the engine.  This has a number of benefits.</p>
<p>Firstly, much of the code that was previously written in the user interface layer or application layer that dealt with building queries to the engine, parsing results, re-querying, etc. can now be pushed into the engine layer of the application.  This means that the other layers of the application can focus on business logic and presenting results to the end user, instead of needing to be concerned with the specifics of working with the engine to manage queries and results.</p>
<p>Providing the ability to bind XQuery functionality to web-services also opens the platform up to the option of using additional programming languages on the client side.  Previously, writing code to interface with the engine in anything besides .NET and Java was potentially costly and error-prone, but now, any language that is able to invoke a web service can be used to build the client portion of an Endeca-driven application.  These web services can be built either as SOAP-style services, or as simpler REST-style services, and virtually all modern languages have mature frameworks for handling both.</p>
<p>This &#8216;engine-layer&#8217; code can also now be shared across multiple applications or clients, even those written in multiple languages.  A Java-based web application and a native C++ Windows application could both query the same engine, and both take advantage of the shared code that now resides in the engine itself.</p>
<p>Pushing this functionality into the engine layer can have significant performance benefits as well.  Consider an application where there are multiple, prioritized classes of data, and the application is to search the first class of data, and only if there are no results in the first, then search the second, and so on.  If this code were written in the application layer, there could be several sets of communications with the engine before any results are ultimately presented to the user.  However, if this same &#8216;cascading search&#8217; functionality were implemented in the engine using XQuery, there would only be one request to the engine, and one response, regardless of how many of the underlying classes of data needed to be searched.</p>
<p>Another benefit this brings is the potential for reuse, not just within a single organization, but across the community of Endeca users.  Code that is written specifically to reside in the MDEX engine and is not tied to a particular application or user interface is much more likely to be reusable in a broader context.  Endeca is already encouraging users of the Early Access release of IAP 6.0 to contribute reusable XQuery code to EDeN, the Endeca Developer Network.</p>
<h4>Performance and Scale Enhancements</h4>
<p>With the 6.0 version of the IAP, Endeca is continuing its tradition of continual performance improvements from version to version.  With this release, special focus was given to some of the more complex edge cases of search and navigation.</p>
<p>One area of focus is navigable dimensions with extremely deep taxonomic hierarchies.  This is likely to be an especially important improvement for users who have content management systems with deep and complex folder structures or other hierarchical organization schemes.</p>
<p>Another area of focus is on dimensions with multi-valued attributes.  Again, rich content management systems that may have, for instance, many keyword tags, categories, or authors, on a product or document are likely to see more gain from these changes than simpler, flatter data sets.</p>
<p>Actual performance improvements for a particular application will vary, but can be very significant.  In internal testing, Endeca has observed gains in throughput (queries per second) of 30 &#8211; 60% over the current release 5.1 product on many benchmark tests.</p>
<p>Large scale implementations will benefit from major enhancements to management of index data on disk and in memory. This can be especially impactful in cases where extremely rich records are used for findability, but the many of the details of that record are not required to display to the user.  For instance, in a large chemical or parts catalog, an individual component may be described by hundreds of parameters which are potentially important in narrowing a search to that particular item.  However, once found, the most important details such as price and SKU may be simple and straightforward. </p>
<p>These scalability enhancements contribute to the throughput gains mentioned earlier.  Other key metrics also show notable improvements.  One example is large-scale engine process startup times, where Endeca is observing dramatic reductions of 70 &#8211; 95% relative to the 5.1 release.</p>
<h4>Platform Support</h4>
<p>With the 6.0 release, Endeca is completing its transition from 32-bit to the modern 64-bit server architecture.  Optimizations have been made to the full 64-bit versions of the Indexer and MDEX Engine for improved performance on 64-bit platforms.  Forge remains a 32-bit application, though the gains in moving to 64-bit would be slight, as it is more often bottlenecked by disk contention or source data systems than processor and memory resources.</p>
<p>The 6.0 release will support the 64-bit versions of Windows, Sun Solaris, and Red Hat Enterprise Linux.</p>
<h4>Merchandising Workbench</h4>
<p>One new product that is now available alongside IAP 6.0 is Merchandising Workbench.  Merchandising Workbench provides additional functionality on top of Endeca&#8217;s Web Studio that is designed specifically for merchandisers.  This functionality removes the complexity of managing business rules from the task of the merchandiser, and provides a simplified interface for performing the most common merchandising tasks, including a workflow specifically designed for streamlining the process of creating effective product landing pages.</p>
<h4>CAS v1.2</h4>
<p>The latest version of CAS (Content Acquisition System) provides several enhancements to crawling content management systems, including a graphical interface for managing CMS crawls and the ability to run multiple CMS crawls simultaneously, which can be a huge boon to systems that need to pull data from multiple CMSs.</p>
<h4>RAD Framework .NET v1.1</h4>
<p>The new version of the Rapid Application Development Framework for ASP .NET has a number of bug fixes and enhancements.  This framework is intended to jumpstart the process of building a .NET-based Endeca application, and provides code for many common components that can be easily reused.  A Java RAD framework is under development, and is currently in the beta stage.</p>
<h4>Availability</h4>
<p>The Early Access release of IAP 6.0 was made available in May 2008.  The EA release is intended for production use by select customers who see immediate, compelling value.  The EA release is also available as a technology preview for current customers.  Endeca is currently projecting general availability of the 6.0 release later in 2008.  For more detailed information, I encourage you to check out EDeN at <a target="_blank" href="http://eden.endeca.com/">http://eden.endeca.com/</a>
    </p>
<p>I hope this article has provided some helpful insights into the latest version of Endeca&#8217;s flagship product, and how some of its new features may be relevant and important for you.  If you have any questions or comments, I encourage you to comment on this article.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/whats-new-in-endeca-6/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using Custom Utility Methods in Migration Workbench</title>
		<link>http://www.bluefishgroup.com/2008/mwb-custom-utility-methods/</link>
		<comments>http://www.bluefishgroup.com/2008/mwb-custom-utility-methods/#comments</comments>
		<pubDate>Tue, 24 Jun 2008 11:00:00 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Content Migrations]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/2008/mwb-custom-utility-methods/</guid>
		<description><![CDATA[Introduction A core component of the Migration Workbench product (aka, Workbench) is its embedded rules engine, which provides a language for expressing transformations on migration objects. To achieve the transformations often required in migration efforts, a user of Workbench will author migration rules that are intepreted and executed by the embedded rules engine. These rules [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Introduction</a><br />
    </h3>
<p>A core component of the Migration Workbench product (aka, Workbench) is its embedded rules engine, which provides a language for expressing transformations on migration objects. To achieve the transformations often required in migration efforts, a user of Workbench will author migration rules that are intepreted and executed by the embedded rules engine. These rules are authored in an expressive rule language which users can use to read and write properties of source and target objects involved in the migration. The Workbench also permits users to introduce custom utility methods written in Java that can be called from the context of rules. Custom utility methods are helpful for several reasons, which include:</p>
<ol>
<li>Common transformation code can be encapsulated in utility methods and used across rules files without having to duplicate transformation logic. For example, a common transformation rule may be to convert a comma-delimited first name (e.g, Smith, John) to its typical colloquial version (e.g., John Smith) &#8212; this would be perfect behavior to encapsulate in a Workbench custom utility method.</li>
<li>In some cases the MWB rules language is not expressive enough to achieve all of a migration&#8217;s transformation requirements. Custom utility methods can be used in these special cases.</li>
</ol>
<h3>
        <a name="head1" class="section">Prerequisites</a><br />
    </h3>
<p>This document assumes that the reader has the MWB product, including the IDE (Integrated Development Environment) plugins, installed. It is also assumed that the reader can create a valid MWB migration project and perform a batch execution using that project.</p>
<h3>
        <a name="head1" class="section">A Simple Example</a><br />
    </h3>
<p>To demonstrate how to introduce and employ a utility method in a migration project, we will write an extremely simple utility method. The method will print a Hello message to standard out, which will appear in the Workbench console during execution. The Hello message will be followed by a string representation of a target document that it receives as a parameter:</p>
<ol>
<li>In the Workbench IDE, make sure that you are in the Java perspective (See Referenced Images 1.)</li>
<li>Create a new source folder. Give it any name you like. For example, &#8220;src/custom&#8221; (See Referenced Images 2.)</li>
<li>Create a new Java package to contain your class. You can give it any name you like but for this example we will use &#8220;utility.sample.hello&#8221; (See Referenced Images 3.)</li>
<li>Create a new Java class in this package called &#8220;HelloUtil&#8221; (See Referenced Images 4.)</li>
<li>Copy and paste the following code as the implementation for this class:
<pre>
                    <code>
package utility.sample.hello;

import com.bluefishgroup.mwb.object.IMObject;

public final class HelloUtil {

	public static void printHello(IMObject object) {
		System.out.println("Hello " + object);
	}
}
</code>
                </pre>
<p>We now have an implementation for our utility method. Note that the printHello() method is a public static method. This allows us to access the utility method in a static manner from the rules file. We&#8217;ll demonstrate the invocation of this method later. Note that the utility method accepts an IMObject instance as a parameter. The source and target attributes on our document classes implement this interface; we&#8217;ll see how to invoke the method with a valid argument later in this example.</p>
<p>But first let&#8217;s make sure that this class is compiled into the proper location in the MAR/project so that the rules engine can access its implementation at runtime.
		</li>
<li>Ensure that the target output folder for compiled classes is the META-INF/classes directory of the MAR/project. Right click the project folder and select Properties from the pop-up menu. Select &#8220;Java Build Path&#8221; from the navigation tree and then select the &#8220;Source&#8221; tab. You should see the following dialog; ensure that the Default output folder is the project name followed by &#8220;/META-INF/classes&#8221;:
<div align="center">
                    <img src="/article-assets/images/mwb-util-methods/mwb-util-output-folder.jpg" border="0" alt="Fig. 1">
<p class="figure">
                        <b><br />
              Figure 1:<br />
            </b> The default output folder for a Workbench project.</p>
</p></div>
<p>		At this point our utility method should be available when writing our rules. Open any rules file in the project and add the following import statement to the project:</p>
<pre>
                    <code>
import utility.sample.hello.HelloUtil
</code>
                </pre>
<p>		Note that for any custom utility class that we wish to use in a rules file, a corresponding import statement needs to appear at the top of that file. Now we can write a rule in the rules file that invokes the utility method:</p>
<pre>
                    <code>
rule "Print hello message for every document"
when
	document : Document( )
then
	HelloUtil.printHello( document.target );
end
</code>
                </pre>
<p>		This rule matches every Document available in the rules engine during execution, then invokes our custom printHello() method to print a message for the target side of each Document. Recall that the printHello() method takes an IMObject instance as a parameter. For Document instances in the rules engine the source and target attributes are valid values to pass in as IMObjects.</p>
<p>		When you are finished you should have a rules file that looks roughly like:</p>
<pre>
                    <code>
package com.bluefishgroup.mwb.external.vocabulary.acme

import com.bluefishgroup.mwb.external.vocabulary.trial.mfacade.Document
import com.bluefishgroup.mwb.external.vocabulary.trial.mfacade.Document.Source
import com.bluefishgroup.mwb.external.vocabulary.trial.mfacade.Document.Target
import com.bluefishgroup.mwb.external.vocabulary.trial.mfacade.Document.Custom

import utility.sample.hello.HelloUtil

rule "Print hello message for every document"
when
	document : Document()
then
	HelloUtil.printHello(document.target);
end
</code>
                </pre>
<p>We are now finished and can execute a batch that references this rules file. The console should display our debug message for each migration Document. The output we will see should look something like:</p>
<pre>
                    <code>

Hello MObject(091c963880020a0c,[FIFTH_DOCUMENT.txt])
Hello MObject(091c963880020a0f,[FIRST_DOCUMENT.txt])
Hello MObject(091c963880020a12,[FOURTH_DOCUMENT.txt])
Hello MObject(091c963880020a06,[FIFTH_DOCUMENT.txt])
...
</code>
                </pre>
</li>
</ol>
<h3>
        <a name="head1" class="section">Using Third-Party Libraries In Rules</a><br />
    </h3>
<p>The previous example demonstrated a simple but perhaps not very useful example of adding custom behavior to rules transformations via custom utility methods. In more realistic use cases we may need to employ more complex Java functionality than just message printing. It is likely that a reasonably complex transformation would need to invoke a third-party or otherwise external Java library, for example. In this section we will show how to invoke Java behavior that is contained inside a JAR file from the context of rules:</p>
<ol>
<li>Add your third-party JAR to the &#8220;lib&#8221; folder in your MAR/project. For this example, we will use the Apache commons-lang library. After adding the JAR to the lib folder, make sure to add the JAR to your project&#8217;s build path. This step will allow us to use auto-completion and rule validation features when using methods in commons-lang:
<div align="center">
                    <img src="/article-assets/images/mwb-util-methods/mwb-util-add-to-build-path.jpg" border="0" alt="Fig. 2">
<p class="figure">
                        <b><br />
              Figure 2:<br />
            </b> Adding a third-party library to a Workbench project&#8217;s build path.</p>
</p></div>
</li>
<li>Now we can use commons-lang utility methods in a rules file. The IDE will even provide us with auto-completion:
<div align="center">
                    <img src="/article-assets/images/mwb-util-methods/mwb-util-third-party-auto-complete.jpg" border="0" alt="Fig. 3">
<p class="figure">
                        <b><br />
              Figure 3:<br />
            </b> Example of auto-completion for a utility method in a rules file.</p>
</p></div>
</li>
</ol>
<p>	At runtime the MWB loads classes from JARs in the &#8220;lib&#8221; directory and makes them available to the rules engine so we should see our rules that use 3rd-party libraries executed successfully.
	</p>
<h3>
        <a name="head1" class="section">Invoking Third-Party Libraries From Custom Utility Methods</a><br />
    </h3>
<p>In the previous example we invoked a 3rd-party library&#8217;s utility method directly from a rules file. Of course we could have also written a custom utility method that invoked behavior in one or more 3rd-party libraries &#8212; in which case we would still need to provide the 3rd-party library JARs in the project&#8217;s &#8220;lib&#8221; directory to ensure its classes were available at runtime.</p>
<h3>
        <a name="head2" class="section">Performance Concerns</a><br />
    </h3>
<p>One concern in developing and invoking custom utility methods from rules is the potential negative impact on rules engine performance. A method invoked in the right-hand side of a rule will be potentially invoked several times within a rules engine session. If care is not taken to make custom utility methods fast, the execution time of the MWB rules engine could grow with the introduction of a utility method.</p>
<h3>
        <a name="head3" class="section">Conclusion</a><br />
    </h3>
<p>Custom utility methods offer a powerful way to develop and encapsulate behavior that can be used from within Migration Workbench transformation rules. These utility methods can employ third-party libraries to achieve transformation or other logic (logging, for example) not easily achieved in the rules language. The usage of custom utility methods can have a negative impact on rules engine performance, but when care is taken they offer a powerful means of introducing extra behavior in MWB rules.</p>
<h3>
        <a name="head1" class="section">Referenced Images</a><br />
    </h3>
<ol>
<li>Use the Window menu to switch to the Java perspective.
<div align="center">
                    <img src="/article-assets/images/mwb-util-methods/mwb-util-java-perspective.jpg" border="0" alt="Fig. 4">
<p class="figure">
                        <b><br />
              Figure 4</b>
                    </p>
</p></div>
</li>
<li>While in the Java perspective, right-click the MWB project and choose New -&gt; Source Folder. At the prompt, type the name of the source folder. For example, &#8220;src/custom&#8221;.
<div align="center">
                    <img src="/article-assets/images/mwb-util-methods/mwb-util-new-source-folder.jpg" border="0" alt="Fig. 5">
<p class="figure">
                        <b><br />
              Figure 5</b>
                    </p>
</p></div>
<div align="center">
                    <img src="/article-assets/images/mwb-util-methods/mwb-util-new-source-folder-modal.jpg" border="0" alt="Fig. 6">
<p class="figure">
                        <b><br />
              Figure 6</b>
                    </p>
</p></div>
</li>
<li>Use Right+Click, New -&gt; Package to create a new package. Then fill in the dialog that will pop-up:
<div align="center">
                    <img src="/article-assets/images/mwb-util-methods/mwb-util-new-package.jpg" border="0" alt="Fig. 7">
<p class="figure">
                        <b><br />
              Figure 7</b>
                    </p>
</p></div>
<div align="center">
                    <img src="/article-assets/images/mwb-util-methods/mwb-util-new-package-modal.jpg" border="0" alt="Fig. 8">
<p class="figure">
                        <b><br />
              Figure 8</b>
                    </p>
</p></div>
</li>
<li>Right+click the Java package and select New -&gt; Class. Fill in the class details and select OK. The new class should appear in the selected Java package.
		</li>
</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/mwb-custom-utility-methods/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New Article: Planning for the Data Migration that&#8217;s Lurking in Your Content Migration</title>
		<link>http://www.bluefishgroup.com/2008/new-article-planning-for-the-data-migration-thats-lurking-in-your-content-migration/</link>
		<comments>http://www.bluefishgroup.com/2008/new-article-planning-for-the-data-migration-thats-lurking-in-your-content-migration/#comments</comments>
		<pubDate>Mon, 09 Jun 2008 21:36:05 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/2008/new-article-planning-for-the-data-migration-thats-lurking-in-your-content-migration/</guid>
		<description><![CDATA[Cory Lowder, one of our Migration Engineers, just published an article about how to plan for a content migration project. One of the things we&#8217;ve discovered over the years is that the hard part of migrating content into a content management system is dealing with all the data associated with the content (the metadata, file [...]]]></description>
				<content:encoded><![CDATA[<p>Cory Lowder, one of our Migration Engineers, just published an article about how to plan for a content migration project. One of the things we&#8217;ve discovered over the years is that the hard part of migrating content into a content management system is dealing with all the data associated with the content (the metadata, file properties, classifications, folder paths, relationships, etc.). Cory has some great information about what to expect and how to plan for dealing with the inevitable complications that you will encounter during your migration project.</p>
<p> Read more in <a href="/library/2008/planning-for-lurking-data-migration/">Planning for the Data Migration that&#8217;s Lurking in Your Content Migration</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/new-article-planning-for-the-data-migration-thats-lurking-in-your-content-migration/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Planning for the Data Migration that&#8217;s Lurking in Your Content Migration</title>
		<link>http://www.bluefishgroup.com/2008/planning-for-lurking-data-migration/</link>
		<comments>http://www.bluefishgroup.com/2008/planning-for-lurking-data-migration/#comments</comments>
		<pubDate>Mon, 09 Jun 2008 11:00:00 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Content Migrations]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/2008/planning-for-lurking-data-migration/</guid>
		<description><![CDATA[Introduction Migrating enterprise content from one system to another requires undertaking two separate yet intertwined migration efforts: moving the actual content files and moving the related data. When planning a migration initiative, it&#8217;s easy to overlook the data migration that is implied in the process. Yet the majority of problems encountered during content migrations are [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Introduction</a><br />
    </h3>
<p>Migrating enterprise content from one system to another requires undertaking two separate yet intertwined migration efforts: moving the actual content files and moving the related data. When planning a migration initiative, it&#8217;s easy to overlook the data migration that is implied in the process. Yet the majority of problems encountered during content migrations are actually problems with the data, which includes the obvious metadata as well as the not so obvious data components such as ownership, security and permissions, folders, workflow and lifecycle state, version stack, and audit history. This article describes the types of problems you can expect to see when moving the content&#8217;s data and explores options for planning and performing the migration of the data that is related to your content.</p>
<h3>
        <a name="head2" class="section">How Big is the Iceberg?</a><br />
    </h3>
<p>Upon first glance, migrating content from one repository into another &#8211; or even from a filesystem into a repository &#8211; seems simple. There are tools that allow you to map the attributes from the source system to their corresponding attributes in the target system, then push a button and watch the content move. However, in practice it&#8217;s rarely this simple. To understand the potential pitfalls in even the simplest content migrations, let&#8217;s turn to the familiar iceberg metaphor.</p>
<div align="center">
        <img src="/article-assets/images/Iceberg-tip.JPG" border="0" alt="Fig. 1: Obvious attribute mappings are just the tip of the iceberg.">
<p class="figure">
            <b><br />
              Figure 1:<br />
            </b> The Tip of the Iceberg</p>
</p></div>
<p>The visible portion of the iceberg represents the attributes that can be mapped in a straightforward fashion. For example, object_name in the source system might map to object_name in the target system, while doc_no in the source system might map to document_number in the target. But lurking below the waterline is a continent of challenges and issues &#8211; issues related to attribute transformations, attributes requiring enrichment, and exceptions. We can cast these challenges as different strata in the iceberg; the deeper you go, the more complex or challenging the issues become.</p>
<div align="center">
        <img src="/article-assets/images/Iceberg-full.JPG" border="0" alt="Fig. 2: Watch out for what's below the water line.">
<p class="figure">
            <b><br />
              Figure 2:<br />
            </b> The Full Iceberg</p>
</p></div>
<h3>
        <a name="head3" class="section">Dealing with the Iceberg</a><br />
    </h3>
<p>Each layer of the iceberg presents its own unique challenges and must be planned for differently. The one common theme is that your approach and plan must anticipate that you will find problems once you begin looking at migrated content and data in the target system.</p>
<h4>Straightforward Attribute Mappings</h4>
<p>Many of the attributes in your source repository will map seamlessly to your target repository. Since these mappings are, well &#8211; straightforward, this part of your migration specification usually gets the most attention. Your intuition for how to plan this part of the migration will probably serve you well &#8211; it boils down to doing a little bit of analysis as you plan.</p>
<p>At Blue Fish we&#8217;ve developed a set of best practices that has served us well across a broad range of content migration efforts. Start with your target repository&#8217;s object model and understand where each attribute will come from. If your source system is a Documentum docbase or another formal content repository, it&#8217;s likely that many of the attribute values will map directly from attributes in that system. If your source is a filesystem, there will be fewer explicit attributes to pull from. In either case, some values may require transforming, which we will discuss in the next section.</p>
<p>Next, analyze your source documents. Does your legacy system have all the metadata that the target repository requires? If not, we deal with those missing values in the next two sections.</p>
<p>Assess the quality of the metadata. Do the values exist? Are they complete? Are they valid? Are they in the expected format?  For example, are all dates &#8220;mm/dd/yyyy&#8221;, or are some &#8220;dd/mm/yyyy&#8221; or &#8220;dd-mm-yyyy&#8221; or &#8220;dd-MMM-yy&#8221; or &#8220;Month dd, yyyy&#8221; or  &#8220;mm/dd/yyyy hh:mm:ss&#8221; and so on. Were users consistent in how they tagged and classified documents?  Did the legacy system enforce consistency? An invalid or incomplete value moved into a non-critical target attribute may be a nuisance, but a missing or invalid value moved into a mandatory target attribute will cause your migration to fail.</p>
<p>Things to watch out for:</p>
<ul>
<li>A migration is a great opportunity to do some housekeeping to ensure that you migrate only relevant content. How will you identify and exclude documents that you don&#8217;t want to migrate? For example, will you migrate only major versions (v1.0, 2.0, 3.0&#8230;) and leave behind the minor revisions (v1.1, 1.2, 2.1, 2.2&#8230;)? Should you screen out documents for products no longer in service? Will you archive documents more than 7 years old instead of migrating them to the new system?</li>
<li>Having analyzed the quality of your metadata, don&#8217;t place too much reliance on that analysis (more on this later). You must plan to encounter exceptions resulting from inconsistent or incomplete metadata values and be prepared to handle them when they arise.</li>
</ul>
<h4>Attribute Transformations</h4>
<p>The first submerged layer of the iceberg consists of the complex mappings we call attribute transformations. For example, if in the source system the author_name is &#8220;John Smith&#8221; but it must be &#8220;Smith, John&#8221; in the target, the value must be transformed during the migration into the new format.</p>
<p>To use a transformation, you must be able to programmatically derive the value of the target attribute from information in the source repository, such as the document&#8217;s folder path, owner, or other attributes. Many transformations are expressed in terms of conditional statements. For example, you may need to set an archived attribute to true only if the document is more than 3 years old.</p>
<p>Some common types of transformations we&#8217;ve seen include:</p>
<ul>
<li>
            <strong>String manipulation</strong> &#8211; repeating the example above, in the source system the author_name is &#8220;John Smith&#8221; but it must be &#8220;Smith, John&#8221; in the target</li>
<li>
            <strong>Date arithmetic</strong> &#8211; take the creation_date attribute in the source, add 180 days to it and set it into a target attribute called review_date</li>
<li>
            <strong>Combining attributes</strong> &#8211; the first_name and last_name in the source system are combined to create the target value called full_name</li>
<li>
            <strong>Splitting attributes</strong> &#8211; splitting street address, city, state, and zip code out of a single address attribute in the source system and putting them into individual target attributes</li>
<li>
            <strong>Parsing</strong> &#8211; starting with a date field with the format &#8220;01/31/98&#8243;, pull out the year and reconstruct the 4 digit year of 1998</li>
<li>
            <strong>Deriving attribute values from other attributes</strong> &#8211; if a document is in a source system folder called &#8220;Invoices&#8221;, then the doc_type is &#8220;invoice&#8221;; if the file name contains the string &#8220;-APP&#8221;, then the doc_status is &#8220;APPROVED&#8221;</li>
</ul>
<p>Planning for this part of the iceberg is similar to planning for the straightforward mappings. In fact, you can often do the analysis for transformations at the same time you are analyzing for the straightforward mappings. The main reason that we think of transformations as more challenging is that they can frequently get out of control, adding a lot of complexity to what you may have thought was a simple migration. It&#8217;s not uncommon to build up a transformation that evaluates the values of three or more source attributes. In a recent migration, I recently had a transformation that required evaluating three document level attributes and one folder level attribute to determine whether a document&#8217;s status was &#8220;draft&#8221; or &#8220;released&#8221; in the target system.</p>
<p>Things to watch out for:</p>
<ul>
<li>Inconsistently applied naming conventions &#8211; if you are deriving an attribute value from the name of the content file, don&#8217;t expect 100% compliance with the stated naming convention. If human beings created the file names, there will be exceptions.</li>
<li>Attributes that were not used for their intended purpose &#8211; some of the more interesting exceptions arise from well-intended users hijacking attributes and using them for something different on &#8220;just these 5 documents&#8221; or for &#8220;just this one customer&#8221;.</li>
<li>If you use the folder path as part of your transformation, how will you deal with documents that are linked into multiple folders?</li>
<li>Mappings that require complex transformations (if you have these cases, you need to know before you select your migration tool, since most tools can&#8217;t do this sort of thing). For example, version stacks that need to be joined or split, separate documents in the source that need to be treated as renditions of the same document in the target, and attribute values from the current version needing to be applied to all versions in the version stack.</li>
</ul>
<h4>Enriched Attributes</h4>
<p>After you deal with attribute transformations, you&#8217;ll face an even greater challenge: target attributes whose values cannot be mapped or programmatically derived from information in the source repository. Typically, this is the case when either the source system has no corresponding attribute or the source attribute was not mandatory (and therefore not populated). Enrichment is basically a last resort when there is no programmatic means for providing the target attribute values.</p>
<p>These attributes require users to &#8220;enrich&#8221; the data in a manual or semi-automated fashion, supplying the missing data based on their knowledge of the content, the system, and the related business processes. For example, if a document is missing its title, the author of that document must go back and add a title before the document can be migrated.</p>
<p>When planning enrichment activities, give some thought to who is best suited to do the work. Since enrichment activities require users with an understanding of the business context, plan to have the right business user(s) enrich the right set of attributes. You can divide the content into enrichment groups and route each group to the user(s) with the relevant knowledge. This is especially useful if the schedule is tight since it allows you to parallelize the enrichment process, Or if knowledge about specific attribute values is segmented across departments, you can slice the enrichment process and have different users enrich different attributes. And make sure you work with the appropriate managers to allocate time for the selected business users.</p>
<p>Even though knowledgeable users are providing the missing values, don&#8217;t expect them to get it right on the first try. Build in safeguards. For example, if you are using an Excel spreadsheet to capture missing attribute values, use drop down lists to ensure consistency and completeness and avoid data entry mistakes. If a drop down list must match the data dictionary in the target system, make sure you export the latest version of the list before starting enrichment, and periodically refresh the list if needed.</p>
<p>In addition to drop down lists, provide a default value so that the attribute value cannot end up blank. As a last resort you could default to the object owner&#8217;s name for future resolution. Have the enrichment process provide immediate feedback for potential errors. For example, use the built-in data validation capabilities of Excel to prompt the user to correct errors immediately. And lastly, be prepared to validate or otherwise check the results of enrichment activities.</p>
<p>To determine the duration of the expected enrichment activities, run a sample set through your enrichment process. Since attribute enrichment is basically a linear process, you can safely project a completion date based on the time it took to complete the sample set, after adding in a reasonable amount of schedule contingency.</p>
<p>Don&#8217;t try to use a statistical sample (again, more on this later). Instead, query your source repository to determine exactly which documents are missing necessary attribute values. You&#8217;ll need a separate query for each attribute. In a Documentum repository, an example would be &#8220;select * from dm_document (all) where title is nullstring&#8221;.</p>
<p>Finally, select a migration tool that directly consumes the enriched attribute values. This speeds up the process and avoids translation or transcription errors.</p>
<p>Things to watch out for:</p>
<ul>
<li>Don&#8217;t forget about older versions &#8211; just because the current version of a document has all its attributes doesn&#8217;t mean that the older versions do. These older versions will cause the migration to fail if you don&#8217;t have a way to deal with them.</li>
<li>If your migration tool uses a staging area between the source and the target, you might be tempted to enrich the data at this point. Beware, because if you have to export your data again, you&#8217;ll overwrite your previously enriched attributes.</li>
<li>Business users are busy people and will not be thrilled with having to enrich their data, especially their old data they don&#8217;t use anymore. Plan your diplomatic request for their time and allocate more time than you think it will take.</li>
</ul>
<h4>Exceptions</h4>
<p>Now we are into the deepest and darkest region of the iceberg. This is where most migrations go wrong, because the approach failed to expect the unexpected. Most exceptions won&#8217;t be discovered until you start migrating data into the target repository. Identifying and addressing them is where you will spend most of your time, so you&#8217;d best plan for it.</p>
<p>The following list of examples is by no means complete but will give you a flavor of the variety and severity of exceptions you can expect to encounter.</p>
<ul>
<li>Documents with missing or incomplete attribute values</li>
<li>Unexpected formatting, such as inconsistent capitalization and white space at the beginning of a string</li>
<li>Attributes with values that don&#8217;t exist in the target repository, such as owners who have left the company or IDs for products that have been discontinued</li>
<li>Documents whose file names don&#8217;t conform to naming conventions or otherwise break your attribute transformations</li>
<li>Unexpected data, such as a company name in the author field</li>
<li>Immutable objects &#8211; by default, objects in a Documentum repository become immutable when they are not the current version.</li>
<li>Interdependencies and potential circular relationships with users, groups, ACLs, relations, and virtual documents &#8211; each object can have dependencies on other objects in the source repository as well as the target repository. For example, if you are migrating the document owner as part of the document object&#8217;s metadata, that owner needs to exist as a valid user in the target system before you try to import the document.</li>
<li>Migrating the workflow state of a document that is somewhere between the initial and final workflow states &#8211; usually these intermediate states are &#8220;non-attachable&#8221;, meaning you cannot set the document to this intermediate state after importing it.</li>
<li>Old content files whose file format or version is not supported by the target system</li>
</ul>
<p>There are four ways of dealing with exceptions:</p>
<ol>
<li>Correct the source data &#8211; Sometimes you can resolve an exception by updating the source data. If a document&#8217;s name doesn&#8217;t conform to the naming convention, update it so that it does. This approach may not always work, since the source system likely contains immutable objects or regulated content that can&#8217;t be changed without an approval process.</li>
<li>Update the migration specification &#8211; if your migration tool supports conditional transformations, you may be able to resolve some exceptions by updating the migration specification to treat the document in question differently. For example, if a document does not conform to the naming convention, you can encode the migration tool to detect this case and apply a different naming convention. The danger of this approach is that your migration specification can quickly get out of hand and will soon have so many exceptions encoded into it that debugging and maintenance become a nightmare.</li>
<li>Further enrich the metadata &#8211; if your migration tool supports external enrichment, you may be able to resolve your exceptions by manually specifying the exact values for each exception. This is likely the most time consuming approach.</li>
<li>Do nothing &#8211; at some point, the effort it takes to handle an exception may not be worth it. An example might be a document is no longer in active use and is just being migrated for archive purposes. If it has several exceptions or requires enrichment, you may decide not to migrate the document after all, or to migrate it into a &#8220;parking lot&#8221; folder to be dealt with at a later time.</li>
</ol>
<p>One of the things that makes exception handling particularly hard is that some exceptions will be &#8220;hiding behind&#8221; other exceptions. What I mean by this is that a document might have two exceptions, but you won&#8217;t know about the second exception until you resolve the first exception. For example, you may find a set of documents whose document_type attribute is not populated. To resolve this exception, you decide to change your migration specification, populating the document_type based on the naming convention of the folder the document is linked into. You then re-run your migration, only to discover that some folders don&#8217;t conform to the naming convention.</p>
<p>We&#8217;ve found the most effective way of dealing with exceptions is to <strong>find them early</strong> and <strong>fix them iteratively</strong>. Start performing migrations right away, perhaps into a test environment. Then run your migration again &#8211; you&#8217;ll find new exceptions that need to be resolved. Plan on having many, many iterations. Most migration tools can&#8217;t process documents incrementally, so either select one that can or plan each iteration to have enough time to roll back your migration and rerun it from scratch.</p>
<p>At Blue Fish, we use a methodology we call Agile Migrations, where we perform frequent, incremental migrations during which we only re-migrate the small number of documents that have changed. Having worked on migrations for years, I can tell you that this beats the old &#8220;big-bang&#8221; approach hands down.</p>
<p>Additional planning steps that will keep you out of trouble include:</p>
<ul>
<li>Keep an exception log so that you can track all the issues that need to be resolved</li>
<li>Plan on keeping detailed records of the status of each document &#8211; your business users will want to know which documents have migrated successfully and which still have issues that need to be resolved</li>
<li>Try to segment your high priority documents from your low priority documents, migrating the critical documents first. The low priority documents can be migrated on a different schedule.</li>
</ul>
<h3>
        <a name="head4" class="section">The Perils of Sample Data Sets</a><br />
    </h3>
<p>One of the most common migration planning mistakes is to employ an approach that runs one or more sample sets through the migration process and then projects a migration timeline based on the analysis of the samples. If you&#8217;ve learned one thing from this article, hopefully it is that it&#8217;s very hard to predict how many errors and exceptions you&#8217;ll encounter during the migration process. Even a statistically valid sampling of the data will give you a false sense of security since you are certain to run into exceptions that were not found in the sample set.</p>
<p>We learned this lesson the hard way. Several years ago we embarked on an effort to migrate 600,000 documents from three Documentum source repositories and one fileshare into a new consolidated Documentum repository. Determined to exercise due diligence in the planning stage, we started off by compiling a list of 150 assumptions about the state of the content and metadata. For example, we assumed that every document had an object name. We scripted DQL statements and programmatically validated all of these assumptions.</p>
<p>After validating the assumptions, we divided the documents into 350 batches. The plan was to run 20 of the batches, representing 6% of the total content to be migrated, through the migration process. We expected this test drive to uncover 80% of the exceptions. However, all 20 batches had their unique problems that required specific handling. At this point we realized we could not predict the number of exceptions and shifted our approach to expect exceptions and facilitate addressing them as they arose.</p>
<p>In summary, the smart and sane approach is to expect exceptions and be prepared to handle them <em>when, not if</em>, they arise.</p>
<h3>
        <a name="head5" class="section">Conclusion</a><br />
    </h3>
<p>Before tackling a content migration initiative, remember the iceberg. The straightforward attribute mapping is just the tip. Each layer has its own challenges and requires different planning. Exceptions take most of the time, and planning to respond quickly to the exceptions boils down to three things:</p>
<ol>
<li>Expect exceptions.</li>
<li>Have the right resources available and prepared to respond to the exceptions <strong>when</strong> they arise.</li>
<li>Migrate early and often, finding and resolving exceptions iteratively.</li>
</ol>
<p>Following this approach and setting the right expectations up front will prepare everyone for the challenges. When data issues and exceptions are spotted in the target system and quickly addressed, the migration team and business users alike will realize the process is &#8220;working as designed&#8221;. Everyone will see the progress and feel confident that the migration effort will be successful and will be completed on time. And you will feel a sense of accomplishment and relief knowing you successfully charted the iceberg and navigated around it instead of colliding with it.</p>
<p>To learn more about the tools and processes we use here at Blue Fish, visit the <a target="_blank" href="http://bluefishgroup.com/content-migrations/about-content-migrations-practice.php">Content Migrations</a> section of our Web site.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/planning-for-lurking-data-migration/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Case Study: Access to Government Regulations, Minus the Red Tape—Regulations.gov</title>
		<link>http://www.bluefishgroup.com/2008/case-study-access-to-government-regulations-minus-the-red-tape-regulations-gov/</link>
		<comments>http://www.bluefishgroup.com/2008/case-study-access-to-government-regulations-minus-the-red-tape-regulations-gov/#comments</comments>
		<pubDate>Tue, 27 May 2008 21:42:39 +0000</pubDate>
		<dc:creator>Leighton Hendrick</dc:creator>
				<category><![CDATA[Case Studies]]></category>
		<category><![CDATA[Information Access]]></category>
		<category><![CDATA[information access]]></category>
		<category><![CDATA[Regulations.gov]]></category>

		<guid isPermaLink="false">http://bluefishgroup.wpengine.com/?p=763</guid>
		<description><![CDATA[It&#8217;s hard to think of the phrase &#8220;government initiative&#8221; without picturing the red tape that comes with it. Luckily, nobody understands this better than the government itself – which is why over 160 government agencies came together in 2003 to make at least one aspect of their work more manageable for American citizens. The project [...]]]></description>
				<content:encoded><![CDATA[<p><a href="http://bluefishgroup.wpengine.com/wp-content/uploads/2013/02/regulations-gov-logo-120px.gif"><img class="alignleft  wp-image-756" style="margin: 5px 10px;" alt="Regulations.gov" src="http://bluefishgroup.wpengine.com/wp-content/uploads/2013/02/regulations-gov-logo-120px.gif" width="120" height="36" /></a>It&#8217;s hard to think of the phrase &#8220;government initiative&#8221; without picturing the red tape that comes with it. Luckily, nobody understands this better than the government itself – which is why over 160 government agencies came together in 2003 to make at least one aspect of their work more manageable for American citizens.<br />
<br />
The project was part of a new eRulemaking Program. Its goal was to create www.regulations.gov, a clearinghouse for all regulatory-related information from the federal government, serving the 300 million citizens in the general public by making it easier to find, view and comment on these regulations. Put simply, it was a way to ensure that U.S. citizens understand what&#8217;s going on in government agencies as varied as the EPA and the IRS, and that public opinion is being heard.<br />
<br />
&#8220;Prior to the launch of the site, if someone wanted to comment on a rule, they&#8217;d have to go to a particular agency&#8217;s Web site, for the handful of agencies that posted regulations online, to see if they had posted something,&#8221; says Patrick Micielli, OEI, OIC and eRulemaking PMO. &#8220;You could type up comments and then, if you could find an address, you could mail them in. In the past there were a lot of mass mailings— a special interest group might send in 50,000 postcards.&#8221;<br />
<br />
All that has changed. Now, regulatory updates are posted daily, Monday through Friday, and citizens can comment online, at one site, without going to other sites or sending in a forest&#8217;s worth of mail. This not only saves the general public time and encourages participation – it also makes it more efficient for agencies to review feedback, ultimately saving taxpayer dollars.<br />
<br />
Working with mountains of information was no simple task. The biggest challenge was organizing the data so that visitors could easily find and comment on whatever regulations they were interested in. In late 2007 Lockheed Martin, a government contractor working on the transition, brought Blue Fish Development Group in to strategize a solution.<br />
<br />
&#8220;If keeping track of information is difficult within one organization, you can imagine how much more complex the challenge became when we combined content from nearly 160 federal agencies and needed to manage the feedback from millions of citizens,&#8221; says Micielli.<br />
<br />
Together with Lockheed and the government agency overseeing the site—The Environmental Protection Agency—Blue Fish was able to untangle the complex problem by leveraging Endeca&#8217;s technology to improve the way users search and navigate the site.<br />
<br />
Dave Claflin, Information Access Practice Manager for Blue Fish, led the project. One question faced by his team was how to best support an extremely broad user base.<br />
<br />
&#8220;We wanted to make the site user friendly for everyone from a farmer to a professor to a lobbyist,&#8221; says Claflin. &#8220;We knew people with very different levels of technical ability would be coming in—from local vegetable growers wondering whether they can call their produce organic to tech-savvy consultants being paid to monitor and influence legislation.&#8221;<br />
<br />
Much of the data was labeled in a manner that gave no clue as to the content. For example, a regulations document might be called Title Twelve, with nothing to indicate what the regulation concerned. Users often struggled to find what they were seeking.<br />
<br />
Blue Fish solved the problem by creating a search solution that crawls both the metadata and content of millions of documents, allowing users to enter practical search terms and receive results for everything containing those keywords. The results can then be refined easily through a helpful guided navigation tool, narrowing things down to exactly what the users are looking for.<br />
<br />
&#8220;The search engine was a very big success,&#8221; says Micielli. &#8220;Running a search now is much simpler, faster and far more intuitive.&#8221;<br />
<br />
Before the Blue Fish solution, users had to wait up to five minutes to get results. Now, not only are searches completed in milliseconds &#8212; they are far more thorough, and visitors are able to track down what before was buried.<br />
<br />
&#8220;The agencies are able to save time, too, because they can access user comments immediately,&#8221; says Micielli. And for a government agency, not only is time money – it also affects how long it takes for important federal legislation to move forward.<br />
<br />
All in all, Micielli and his colleagues are extremely pleased with the solution. &#8220;Blue Fish put a lot of effort into deploying the search technology and revamping the site in less than three months. Now people aren&#8217;t frustrated when they visit Regulations.gov, because they can immediately find the information they&#8217;re looking for. I&#8217;m really impressed with Blue Fish&#8217;s work.&#8221;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/case-study-access-to-government-regulations-minus-the-red-tape-regulations-gov/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New Article: An Introduction to Web Publishing Jobs in Documentum</title>
		<link>http://www.bluefishgroup.com/2008/new-article-an-introduction-to-web-publishing-jobs-in-documentum/</link>
		<comments>http://www.bluefishgroup.com/2008/new-article-an-introduction-to-web-publishing-jobs-in-documentum/#comments</comments>
		<pubDate>Tue, 13 May 2008 21:22:13 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/2008/new-article-an-introduction-to-web-publishing-jobs-in-documentum/</guid>
		<description><![CDATA[One of our consultants, Nicki DuBose, just published an article about Web Publishing Jobs in Documentum. Jobs are administrative tasks that run at various times to clean up log files, publish content, delete orphaned content and things like that. Jobs are surprisingly hard to figure out when you&#8217;re just getting started, and Nicki does a [...]]]></description>
				<content:encoded><![CDATA[<p>One of our consultants, Nicki DuBose, just published an <a href="http://www.bluefishgroup.com/library/2008/introduction-to-wp-jobs/">article about Web Publishing Jobs in Documentum</a>. Jobs are administrative tasks that run at various times to clean up log files, publish content, delete orphaned content and things like that. Jobs are surprisingly hard to figure out when you&#8217;re just getting started, and Nicki does a great job of explaining all the settings and how to configure them. She also explains which jobs are the most important and offers recommendations for how frequently they should be scheduled to run.</p>
<p>Read more at <a href="http://www.bluefishgroup.com/library/2008/introduction-to-wp-jobs/">An Introduction to Web Publishing Jobs in Documentum</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/new-article-an-introduction-to-web-publishing-jobs-in-documentum/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>An Introduction to Web Publishing Jobs in Documentum</title>
		<link>http://www.bluefishgroup.com/2008/introduction-to-wp-jobs/</link>
		<comments>http://www.bluefishgroup.com/2008/introduction-to-wp-jobs/#comments</comments>
		<pubDate>Tue, 13 May 2008 11:00:00 +0000</pubDate>
		<dc:creator>Nicki DuBose</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Web Content Management]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/2008/introduction-to-wp-jobs/</guid>
		<description><![CDATA[Overview Documentum provides a number of out-of-the box administrative jobs that help administrators ensure the health and integrity of the Documentum environment. For example, there is a job to check the consistency and integrity of the objects in the repository and a job to remove the old audit trail entries. In addition to the standard [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Overview</a><br />
    </h3>
<p>Documentum provides a number of out-of-the box administrative jobs that help administrators ensure the health and integrity of the Documentum environment. For example, there is a job to check the consistency and integrity of the objects in the repository and a job to remove the old audit trail entries.</p>
<p>In addition to the standard jobs that ship with the content server, there are several jobs delivered with Web Publisher and Site Caching Services (SCS) that automate the clean-up and publishing of content in web publishing environments. For example, the dm_WebPublish job publishes content from the repository to a website.</p>
<p>This article will provide an overview of the jobs used in the web publishing environment: what they are, recommended configuration, and troubleshooting tips for some of the more common errors.</p>
<h3>
        <a name="head2" class="section">What is a job?</a><br />
    </h3>
<p>Jobs in Documentum are used to automate the execution of a program or script.  Each job in Documentum represents an automation schedule and execution frequency for something called a method, which in turn holds the reference to the program or script to execute.</p>
<p>Jobs are configured in Documentum Administrator (DA) under Administration-&gt;Job Management-&gt;Jobs.  To view the properties, schedule, method, and object information for a job, click on the information icon in DA.</p>
<p>Selecting the &#8220;Pass Standard Arguments&#8221; on the method tab page will result in the following default argument values:</p>
<p>    <well_formed_html></p>
<table>
<tr>
<td>docbase_name</td>
<td>[name of docbase]</td>
</tr>
<tr>
<td>user_name</td>
<td>[docbase owner]</td>
</tr>
<tr>
<td>job_id</td>
<td>[r_object_id of the dm_job object]</td>
</tr>
<tr>
<td>method_trace_level</td>
<td>0</td>
</tr>
</table>
<p>    </well_formed_html></p>
<p>The method uses these arguments to log into the docbase to accomplish its intended purpose.</p>
<div align="center">
        <img src="/article-assets/images/pass-standard-args.jpg" border="0" alt="Fig. 1: Pass Standard Args Image">
<p class="figure">
            <b><br />
              Figure 1:<br />
            </b> Pass Standard Arguments on the Method tab of the Job Properties</p>
</p></div>
<p>Another argument commonly used in job configuration is the window_interval.  This argument defines a range of time in which the job can start outside of its scheduled execution time.  For instance, if a job is scheduled to run every day at 2pm and the window_interval is set to 60 (minutes), then the job can start at any time between 1pm and 3pm.  This interval can be useful if the Content Server is down at the scheduled execution time, then the job will run if the current time is within the current window interval.  Using my example of 2pm, if the content server went down at 1:30 and was restored at 2:30, the job execution process would attempt to run the job in the remaining half hour window (2:30 &#8211; 3:00).  Setting the interval to 1440 (24 hours) will guarantee the job will run, but may also negatively impact performance.</p>
<p>The execution of jobs is handled by the agent exec process.  On the Content Server, the agent exec process runs continuously, polling for new jobs to execute.  By default, the agent exec process polls the repository for jobs to execute every 60 seconds. When the process finds more than one job to execute in a cycle it will execute each job, sleeping 30 seconds between each. The number of jobs executed in a single polling cycle is configurable; by default, the agent exec process will execute up to three jobs in a polling cycle.  To change this value, modify the max_concurrent_key value in the dmcl.ini.  For more information on the agent exec process and modifying the polling interval, see the <em>Content Server Administrator&#8217;s Guide</em>.</p>
<h3>
        <a name="head3" class="section">Jobs for Web Publishing</a><br />
    </h3>
<p>Now that we&#8217;ve introduced the basics about Documentum jobs, let&#8217;s discuss the jobs used in the web publishing environment.  Web Publisher and SCS provide us with a few jobs to aid in creating, promoting, and publishing content.   To help the content authors with content creation, we have the Create_Dynamic_Content job and the WcmObjectBagJob.  For automatic promotion of content and publishing we have the Monitor_Lifecycles job and the dm_WebPublish_[r_object_id] job, respectively.  Lastly, the dm_SCSLogPurge job is used for housekeeping of the WebCache logs.   Let&#8217;s dive into each one of the jobs&#8230;</p>
<h3>
        <a name="head4" class="section">Create_Dynamic_Content</a><br />
    </h3>
<p>The Create_Dynamic_Content job is used to update certain types of dynamic web pages with the latest content.</p>
<p>In web content management, there is often a requirement to create dynamic web pages &#8211; pages that update automatically based on other content in the repository.  One of the most common types of dynamic page is a listing page; for example, a web page listing all of the latest press releases or announcements.  Each time a user creates or removes a press release, you would expect the press release listing page to be updated automatically.</p>
<p>At Blue Fish, we prefer to create dynamic pages by having the web page query the SCS database. This provides real-time updates and follows a familiar paradigm that most web developers are familiar with. If you create dynamic web pages the way that we do, you won&#8217;t need the Create_Dynamic_Content job.</p>
<p>Web Publisher does, however, provide an alternative approach to creating dynamic web pages in which XDQL queries (Documentum queries that produce XML fragments) are embedded into Web Publisher presentation files (XSL stylesheets). Whenever the file is published, the XDQL query is run and the listing page is updated with the latest press releases.</p>
<p>The Create Dynamic Content job is used to refresh these web pages on a regular schedule so that the pages are always up to date.</p>
<p>To use this job, Web Publisher must know which pages are dynamically generated using the XDQL method. To indicate that a file has dynamically generated content, its template must be flagged to automatically refresh when related content is modified.  To set the flag, select the Content Refresh checkbox on the publishing tab of the content&#8217;s Properties page.  This type of content is created by the transformation process performed by the Create_Dynamic_Content job, which transforms the content using the presentation file containing the XDQL.  The job will only perform this transformation on content in the Active lifecycle state.</p>
<p>An administrator can configure the Create Dynamic Content job to run as frequently as is appropriate for the content types.  The job run frequency should be set based on the freshness requirements of the dynamic content.  For instance, a current press release listing page might be updated daily, but an employee listing might only be refreshed monthly.  Since the Create Dynamic Content job can only be configured once for all content types, frequency should be set based on the content with the highest freshness requirement.</p>
<p>Note that the Create Dynamic Content job does not invoke an SCS publish operation.  For the content to be published to the Active website, configure the dm_WebPublish job to run at periodic intervals.</p>
<div class="callout">
<p>
            <b></b>
        </p>
<p>
            <em>Tip: </em>By default, the Create_Dynamic_Content job is installed in the Active state, so if your site is not using XDQL to generate dynamic content, remember to set the job to Inactive.</p>
</p></div>
<p>    <well_formed_html></p>
<table>
<tr>
<td>Recommended Schedule</td>
<td>varies</td>
</tr>
<tr>
<td>Method invoked</td>
<td>wcmCreateTransformation</td>
</tr>
<tr>
<td>Arguments</td>
<td>check &#8220;Pass standard arguments&#8221;</td>
</tr>
</table>
<p>    </well_formed_html></p>
<h3>
        <a name="head5" class="section">dm_WebPublish_[r_object_id]</a><br />
    </h3>
<p>The dm_WebPublish job is used to automate the process of publishing content from a repository to a website.</p>
<p>Content is more than just files; it includes the properties or metadata that describe the content, as well as any relationships to the content.  To automate the process of publishing all of these elements, you must define a site publishing configuration for Site Caching Services (SCS) in Documentum Administrator (DA). SCS is an application that automates the publishing of content from a Documentum repository to a website &#8211; and a required piece of the Web Publisher puzzle.</p>
<p>Site publishing configurations are created for each web site to identify what type(s) of content will be published, their format, and where to publish the content.  In the site publishing configuration, an administrator defines the properties to publish as well as their destination (table name) in the SCS database.  Once the publishing configuration has been created and tested, an administrator can manually invoke a publish operation by running the site publishing configuration.  Running the site publishing configuration will &#8220;export&#8221; the appropriate content from the Documentum repository to the website location.  It is up to a web developer to create the code or application(s) that will then consume the attributes and relationships published to the SCS database.</p>
<p>Alternatively, the site publishing operation can be automated by activating the dm_WebPublish_[r_object_id] job generated when a site publishing configuration is created.  For each site publishing configuration defined in DA, there is a corresponding dm_WebPublish job that can be configured to automate the publishing task on a regular schedule.  Based on the schedule set on the job, the website can be refreshed with the latest content updates.</p>
<div class="callout">
<p>
            <b></b>
        </p>
<p>
            <em>Note: </em>The r_object_id in the name of the dm_WebPublish job corresponds to the r_object_id of dm_webc_config object, that is, the site publishing configuration object.</p>
</p></div>
<p>    <well_formed_html></p>
<table>
<tr>
<td>Recommended Schedule</td>
<td>Every half hour</td>
</tr>
<tr>
<td>Method invoked</td>
<td>dm_webcache_publish</td>
</tr>
<tr>
<td>Arguments</td>
<td>defaulted from SCS</td>
</tr>
</table>
<p>    </well_formed_html></p>
<h3>
        <a name="head6" class="section">dm_SCSLogPurgeJob</a><br />
    </h3>
<p>The dm_SCSLogPurgeJob is used to delete out-dated SCS log files.</p>
<p>Now that we&#8217;ve covered a little bit about publishing jobs and SCS, we can move onto the logging that occurs with each publish operation.  By default, SCS publishing logs are written to the server&#8217;s file system in the <em>$DM_HOME/webcache/temp directory</em>.  If the trace level is greater than zero on the publishing job or the job fails, then the publishing logs are written to the file system.  As you might imagine, with tracing enabled or multiple publishing failures, you could generate hundreds of log files in a short time.</p>
<p>The dm_SCSLogPurgeJob provided with SCS is intended for clean-up or housekeeping of the SCS publishing logs.  The job does exactly what you&#8217;d expect &#8211; it purges old SCS log files.  Like all of the jobs in Documentum, administrators can designate how often and at what date and time to run the SCS Log Purge job.  In addition, you can regulate the duration of time to keep these log files.  To keep a certain number of days of SCS Log files, set the cutoff days argument.  For instance, set the cutoff_days argument to 30 to keep the last 30 days of SCS log files.</p>
<p>This job also generates a report of all of the files that were deleted and the directories that were inspected for SCS log files.  By default, this report is generated in <em>$DM_HOME/dba/log/[docbase hex id]/sysadmin</em>.  The report is overwritten each time the job executes.</p>
<p>    <well_formed_html></p>
<table>
<tr>
<td>Recommended Schedule</td>
<td>Once per day</td>
</tr>
<tr>
<td>Method invoked</td>
<td>dm_SCSLogPurge</td>
</tr>
<tr>
<td rowspan="3">Arguments</td>
<td>-window_interval 120 -queueperson -cutoff_days 30</td>
<td></td>
</tr>
</table>
<p>    </well_formed_html></p>
<h3>
        <a name="head7" class="section">Monitor_Lifecycles</a><br />
    </h3>
<p>The Monitor_Lifecycles job is used to promote and expire dated web content.</p>
<p>In Web Publisher, content authors can create content with future effective and expiration dates to indicate when content should be published to, or removed from a website.  For instance, a content author might write an announcement about a new product scheduled for release in two weeks.  The author can draft the announcement and get the appropriate approvals prior to the product release date, but set the page to publish to the website in two weeks.  Similarly, you might want to remove a page from a website on a particular date.  For example, you would probably want to remove a product coupon page when the coupon reaches its expiration date.</p>
<p>The purpose of the Monitor Lifecycles job is to automate the promotion and expiration of this type of dated content.  The job enables content authors to create content well in advance of the publish date, and also to ensure that the content can be automatically published (or expired) at a specific time and date.  By setting effective dates on the content and activating the Monitor_Lifecycles job, the content will automatically be promoted to the Active lifecycle state and subsequently be picked up by the dm_WebPublish job for publishing to the website.  Similarly, content will be expired by the job when the expiration date is reached and then removed from the website on the next publish.</p>
<p>The Monitor_Lifecycles job will search the repository for content in the Approved lifecycle state, comparing the effective date on the content to the current date.  If the effective date matches the current date, the job will automatically promote the content to the Active lifecycle state.  The job will promote content in the Approved lifecycle state in two cases- 1)when the effective date is reached or 2) when the effective date is blank and &#8220;delay publish&#8221; is enabled on the lifecycle assigned to the content.  In addition to promoting content to the Active website, the Monitor Lifecycles job will search the repository for content in the Active lifecycle state, comparing the expiration date with the current date and setting the content to the Expired lifecycle state when the expiration date is reached.</p>
<div class="callout">
<p>
            <b></b>
        </p>
<p>
            <em>Note: </em>The Monitor_Lifecycles does not publish content.  You must enable the dm_WebPublish job to publish the newly promoted or expired content to the website.</p>
</p></div>
<p>    <well_formed_html></p>
<table>
<tr>
<td>Recommended Schedule</td>
<td>Every half hour</td>
</tr>
<tr>
<td>Method invoked</td>
<td>wcmLifecycleMonitor</td>
</tr>
<tr>
<td>Arguments</td>
<td>check &#8220;Pass standard arguments&#8221;</td>
</tr>
</table>
<p>    </well_formed_html></p>
<h3>
        <a name="head8" class="section">WcmObjectBagJob</a><br />
    </h3>
<p>The WcmObjectBagJob is used to increase performance in the new content creation process by pre-creating content objects.</p>
<p>Remember, content is more than just a file; it includes properties or metadata, and relationships to the content.  Consequently, creating new content involves creating instances of each of these elements.  To improve the performance time for content authors when creating new content in Web Publisher, Documentum provides a job to pre-create these content objects.  To illustrate the overhead required to create new content, let&#8217;s explore the objects created when a content author chooses to create new content.  In addition to creating the actual file that contains the content, the metadata that describes the content is created and written to the repository.  Also, relationships are created that tie the content to content template(s), rules file(s), and presentation file(s).  Additionally, relationships are created between the content and its corresponding category, workflow and any images or other artifacts linked with the content.</p>
<p>The WcmObjectBagJob can reduce some of the overhead required when creating content by pre-creating a number of these empty content objects.</p>
<p>To enable the WCMObjectBagJob, set the job to Active in DA then set the new content object count in Web Publisher.  To set the new object count in Web Publisher, log on as an administrator and select Admin-&gt; Web Publisher Admin-&gt; Settings-&gt; General tab.  Setting the &#8220;New Content Object Count&#8221; value on the general tab will set the number of objects that will be pre-created when the WCMObjectBagJob runs (the default number is five).  The job only pre-creates objects from Approved content templates.  If the template, rules file, or presentation file is updated then any items in the existing &#8220;object bag&#8221; are replaced with new versions when the job runs.</p>
<div class="callout">
<p>
            <b></b>
        </p>
<p>
            <em>Note: </em>Content created by the WcmObjectBagJob is created with the document owner attribute defaulted to the docbase owner name instead of the name of the content author.  If defaulting the owner of the content to the docbase owner is not desirable for your implementation, we recommend setting the job to Inactive as we do here at Blue Fish.</p>
</p></div>
<p>    <well_formed_html></p>
<table>
<tr>
<td>Recommended Schedule</td>
<td>Nightly</td>
</tr>
<tr>
<td>Method invoked</td>
<td>wcmObjectBagMethod</td>
</tr>
<tr>
<td>Arguments</td>
<td>check &#8220;Pass standard arguments&#8221;</td>
</tr>
</table>
<p>    </well_formed_html></p>
<h3>
        <a name="head9" class="section">Troubleshooting Common Errors</a><br />
    </h3>
<p>Detailed below are some of the most common problems and errors with the web publishing jobs.  These errors can be found in the docbase owner&#8217;s Inbox.</p>
<pre>
        <code>
[ERROR] [LAUNCHER 8728] Detected while preparing job 
Monitor_Lifecycles for execution: Command Failed: execquery, 
s0, F, EXECUTE do_method WITH method =...</code>
    </pre>
<pre>
        <code>
[ERROR] [LAUNCHER 3700] Detected while preparing job 
Create_Dynamic_Content for execution: Command Failed: 
execquery, s0, F, EXECUTE do_method WITH method =...</code>
    </pre>
<p>These errors indicate a problem with the Java Method Server.  If you encounter this type of error, perform the following actions:</p>
<ul>
<li>Validate that the Java Method Server is running</li>
<li>Validate that the wcm.jar and WcmMethods.jar are in the classpath</li>
<ul>
<li>These jars are included through the dctm.jar defined in the classpath variable on the content server and the appserver</li>
<li>Validate the existence of the jars as defined in the dctm.jar manifest file</li>
</ul>
<li>Restart the Java Method Server</li>
</ul>
<pre>
        <code>
[ERROR] [AGENTEXEC 3408] Detected while processing dead job 
Monitor_Lifecycles: The job object indicated the job was in 
progress, but the job was not actually running.  It is likely 
that the dm_agent_exec utility was stopped while the job was 
in progress.</code>
    </pre>
<pre>
        <code>
[ERROR] [AGENTEXEC 1372] Detected while processing dead job 
dm_WebPublish_[r_object_id: The job object indicated the job 
was in progress, but the job was not actually running.  It is 
likely that the dm_agent_exec utility was stopped while the job 
was in progress.</code>
    </pre>
<p>The above errors indicate a failure in the agent exec process that can occur for any job type.  If you encounter this error, perform the following actions:</p>
<ul>
<li>Check the window_interval argument configured on the affected job.  In some cases, the interval may not be large enough to start the job in the allotted time slot</li>
<li>Restart the docbase to release any locks created by the failed agent exec process</li>
<li>Restart the Java Method Server</li>
</ul>
<pre>
        <code>
[ERROR] [LAUNCHER 14516] Detected while completing processing for
 job dm_WebPublish_[r_object_id]: FAILED: Method 
dm_webcache_publish return value was -1.</code>
    </pre>
<p>The above error indicates a failure in the publishing job.  If you encounter this error, perform the following actions:</p>
<ul>
<li>Review the logs on the Content Server in $DCTM_INSTALL$product5.3webcachetemp for more details on the error</li>
<li>Restart the docbase, Java Method Server and SCS on the content server and clear the DMCL cache</li>
<li>Validate that the publishing job is not &#8220;stuck&#8221;</li>
<ul>
<li>Validate that the holder field is empty for the job you are troubleshooting.  (The holder contains a value while the job is running, but it should be empty when the job is complete)</li>
<li>To validate (DQL):</li>
<pre>
                <code>
select * from webc_lock;</code>
            </pre>
<li>If the holder, does not clear in the expected job run time, try clearing the holder value:</li>
<pre>
                <code>Update webc_lock object set holder = '' where r_object_id = '[r_object_id of publishing config]';</code>
            </pre>
</ul>
</ul>
<pre>
        <code>
[FATAL ERROR] [AGENTEXEC 392] Detected while scheduling job 
dm_WebPublish_[r_object_id]: Job a_next_invocation must be 
supplied.</code>
    </pre>
<p>The above error indicates a failure in the agent exec process that can occur for any job type.  If you encounter this error, perform the following actions:</p>
<ul>
<li>This error indicates that the a_next_invocation date on the job is null.  To correct the error using DQL, set the a_next_invocation attribute on the dm_job object to any date in the past.</li>
</ul>
<pre>
        <code>
update dm_job object set a_next_invocation = DATE('04/01/2008') 
where object_name like 'dm_WebPublish%';</code>
    </pre>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/introduction-to-wp-jobs/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Using Migration Workbench to Address Common Content Migration Issues</title>
		<link>http://www.bluefishgroup.com/2008/using-migration-workbench/</link>
		<comments>http://www.bluefishgroup.com/2008/using-migration-workbench/#comments</comments>
		<pubDate>Tue, 13 May 2008 11:00:00 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Content Migrations]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/2008/using-migration-workbench/</guid>
		<description><![CDATA[Introduction Previously I wrote an article about a number of problems we have seen with typical migration approaches. These problems boil down to the following major issues: Poor Data Quality: Most organizations planning a migration do not understand how bad the quality of their source data is. Engaging users to manually clean up this data [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Introduction</a><br />
    </h3>
<p>Previously I wrote an <a href="/library/2007/technical-challenges-faced-during-content-migrations/">article about a number of problems we have seen with typical migration approaches</a>. These problems boil down to the following major issues:</p>
<ul>
<li>
            <strong>Poor Data Quality:</strong> Most organizations planning a migration do not understand how bad the quality of their source data is. Engaging users to manually clean up this data is the most common source of delays.</li>
<li>
            <strong>Source System Freeze:</strong> The typical migration process includes a &#8220;freeze&#8221; on source and target systems.  During the freeze, users are prevented from changing or accessing critical business content.  The source system freeze causes the loudest complaints from users.  They need their content and they need it now!  Compounding the issue is the fact that freezes often go on long beyond the expected timeline due to the time it takes to resolve the multitude of data quality issues.</li>
<li>
            <strong>Migration of Critical Content Delayed by Non-Critical:</strong> Often users are most concerned with a small subset of their important content.  Traditional methods require that the migration team must complete the migration of the entire repository before users can have access to their critical data in the target system.</li>
<li>
            <strong>Data Problems Discovered Late in the Process:</strong> Using traditional migration methods, users don&#8217;t get a chance to see their data until it has been moved into the target, late in the process.  Unfortunately this means that most of the time-consuming and difficult to solve issues are not addressed or even identified until very late in the project lifecycle.</li>
</ul>
<p>After repeatedly working with our clients to overcome these issues we have discovered a number of interesting insights.</p>
<ul>
<li>
            <strong>Rigid One-to-One Mappings are Limiting:</strong>  Attribute transformation schemes involve mapping one attribute in the source to one in the target, often incorporating a data transformation.  This is classic ETL thinking, which really isn&#8217;t effective in content migrations.  It assumes a uniformity of data that just doesn&#8217;t exist.  In the real world users are not consistent in applying conventions, populating mandatory attributes, etc.  Mapping and transformations should be designed to mirror the way users think about their data.</li>
<li>
            <strong>Problems Not Discovered Until Seen in the Target:</strong> Many problems with data quality in the source aren&#8217;t recognized until the users see their data in the target.  Because this happens late in the traditional migration process, it leads to extensive rework and extended timelines.</li>
<li>
            <strong>High-Priority Data is Better Quality Than Low-Priority Data:</strong> The critical data that users demand quick access to is also data they use on a daily basis.  This means it has more eyes on it.  This data is frequently reviewed and updated, often leading to better quality data.  This data will have fewer data problems and will be easier to migrate.</li>
</ul>
<h3>
        <a name="head2" class="section">Design of a Better Migration Approach</a><br />
    </h3>
<p>Blue Fish has developed a new migration approach and tool, called Migration Workbench, based on our experiences and insights.  They are designed around the following concepts:</p>
<ul>
<li>Incremental Migration</li>
<li>Live-to-Live Migration</li>
<li>Dynamic Cutover</li>
<li>Rules-Based Attribute Transformations</li>
<li>Total Visibility into Migration Content</li>
</ul>
<p>Let&#8217;s take a look at some of these concepts.</p>
<p>
        <strong>Incremental Migration</strong>
    </p>
<p>One of the biggest problems with traditional migration approaches is that problems usually aren&#8217;t discovered until the very end of the migration process when users start to see how their documents are filed in the target system or realize that some documents were &#8220;lost&#8221; during the migration.   When this happens, the typical fix is to roll back all migrated content from the target, fix the underlying problems in the source repository, and then rerun the migration.  This process may be repeated hundreds of times until all of the errors are corrected and the process executes flawlessly.  No matter how much you focus on trying to get the migration requirements right up front, there is no practical way to do this without letting the users see their data in the target system.</p>
<p>Migration Workbench lives with this reality and operates on the expectation that data problems will be spotted in the target system.  It expects that attribute mappings will need to be changed, that source data will need to be updated, and that documents will be added and deleted over the course of the migration effort.  Rather than forcing an organization to roll back the migration each time one of these things happens, Migration Workbench will detect these changes and re-migrate the affected documents.  As data errors are discovered, Workbench flags the relevant documents and continues processing other content that is not in error.</p>
<p>
        <strong>Live-to-Live Migration</strong>
    </p>
<p>The concept of live-to-live migration means that both target and source systems remain available during the migration.  Documents migrated into a live target system can be individually &#8216;hidden&#8217; until the time is right to make them available.  If those same documents are changed in the source system, the target is simply updated with those changes.</p>
<p>This means users are not locked out of their critical systems while the migration is underway.  In fact, they will be blissfully oblivious to the fact that, behind the scenes, millions of documents are making their way to the target system.  When it&#8217;s time to cut the users over to the new target system, they don&#8217;t need to know that all you did was hide the documents in the source and exposed the documents in the target.  Let them be amazed at how quickly you &#8216;moved&#8217; all of their content to the new system!</p>
<p>
        <strong>Dynamic Cutover</strong>
    </p>
<p>Another way Workbench makes the migration process less stressful is through dynamic cutover.  Like your business users, we understand that not all content is created equal.  Quickly migrating a small subset of key documents is often the key to keeping users happy.  And since these documents are often the most viewed and used, they are generally the best quality data, requiring the least amount of cleanup.</p>
<p>Workbench allows you to identify, map, migrate, and validate your most valuable content first.  The bulk of lower priority content can then be addressed on a longer timeline without holding the critical content hostage.</p>
<p>
        <strong>Rules-Based Attribute Transformation</strong>
    </p>
<p>Typical migration tools use many different schemes to map content from source to target, but they all essentially boil down to taking data from field A and putting it into field B.  There may be transformations or conversions involved, but the data always goes from a field in the source to a field in the target.  But what if field A was only populated for documents created in the past few months?  What if some departments used field C instead of field A?  In the real world, more data seems to follow the exceptions than follow the conventions.  Basic transformation schemes, common to most ETL based tools, simply don&#8217;t have the flexibility to address real-world content management issues.</p>
<p>Migration Workbench expresses attribute mappings and transformations as simple migration rules.  Complex mappings that used to take Jedi-level manipulations of page after page of mapping expressions are often reduced to one or two simple rules.  And, as an added bonus, those rules match how the business analyst thinks.  One requirement statement documented by the business analyst becomes one easily recognized (and traceable!) migration rule in Workbench.</p>
<p>
        <strong>Total Visibility into Migration Content</strong>
    </p>
<p>Many times in a migration, the real problem isn&#8217;t what users see in the target &#8211; it&#8217;s what they don&#8217;t see.  It might be easy for a user to detect that a migrated document in a list of 100 documents has the wrong title.  However, it is not as easy to see that a list of 100 documents should&#8217;ve been 101 because a document was missing.</p>
<p>Migration Workbench provides &#8220;Total Visibility&#8221; into your migrated documents.  Every document is traceable throughout the migration process.  This includes what rules triggered what data transformations or exceptions.  This data can be retrieved in a set of migration reports that allow for detailed tracking of the migration&#8217;s progress, including full audit traceability.</p>
<p>True, it&#8217;s not easy to detect that a single document is missing from a list of 100 by looking.  And even if you run a query that tells you one document is missing, it&#8217;s hard to tell why.  However, if the migration immediately generates a report stating 100 documents were migrated, and 1 was not because it was missing data in mandatory field X, you suddenly have total visibility into the status of your migration.</p>
<h3>
        <a name="head3" class="section">Benefits of a Better Migration Approach</a><br />
    </h3>
<p>
        <strong>Example Scenario: Acme Plastics</strong>
    </p>
<p>To help show how this new approach to migration works, I&#8217;ve put together an example scenario outlining a few key benefits.  This example looks at Acme Plastics, a company moving their Finance Department&#8217;s documents from an old legacy repository to an updated one with a revamped object model.  I&#8217;ll discuss some of the problems Acme encounters along the way and how these issues are resolved with Migration Workbench and the Blue Fish approach.</p>
<p>
        <strong>Source Repository</strong>
    </p>
<p>Acme&#8217;s finance documents consist of Purchase Orders (POs) and Invoices, currently stored in two folders in a Documentum repository, /Acme/POs and /Acme/Invoices, respectively.  All documents are represented by the object type of &#8220;acme_document&#8221; which, in addition to the standard attributes of <em>owner_name</em> and <em>object_type</em>, have the following custom attributes (see Figure 1):</p>
<ul>
<li>
            <em>contact_name</em> &#8211; the name of the contact at the vendor or customer,</li>
<li>
            <em>retired</em> &#8211; a Boolean indicating the file is over two years old, and</li>
<li>
            <em>contract_date</em> &#8211; the date of the PO or Invoice.</li>
</ul>
<p>Acme personnel are supposed to follow the naming convention of including the PO number or Invoice number at the beginning of every document.  This follows the format: &#8220;POxxxxx&#8221; for POs and &#8220;INVxxxxx&#8221; for invoices. At the end of the fiscal year, all documents older than two years are supposed to be filed in a subfolder called &#8220;old&#8221;.</p>
<div align="center">
        <img src="/article-assets/images/using_mwb_fig1_source_demo.jpg" border="0" alt="Fig. 1: Graphic of Source Repository Structure">
<p class="figure">
            <b><br />
              Figure 1:<br />
            </b> Source Repository Structure</p>
</p></div>
<p>
        <strong>Target Repository</strong>
    </p>
<p>The target repository has a new object model and folder structure (see Figure 2).  Acme is anticipating expanding use of the system to other departments, so the root <em>object_type</em> for the documents to be migrated is changing to be &#8220;finance_document&#8221;, with two subtypes called &#8220;po_document&#8221; and &#8220;invoice_document&#8221;.  Additionally, the PO and Invoice folders contain subfolders for each year, indicating the <em>fiscal_year</em> to which the document belongs.</p>
<div align="center">
        <img src="/article-assets/images/using_mwb_fig2_target_demo.jpg" border="0" alt="Fig. 2: Graphic of Target Repository Structure">
<p class="figure">
            <b><br />
              Figure 2:<br />
            </b> Target Repository Structure</p>
</p></div>
<p>
        <strong>Migration Process</strong>
    </p>
<p>Acme&#8217;s migration analyst has configured Workbench to evaluate all documents in the /Acme cabinet and has identified the following set of migration requirements:</p>
<ul>
<li>If the document exists in the /Acme/POs folder or its subfolders, map it to type &#8220;po_document&#8221;</li>
<li>If the document exists in the /Acme/Invoices folder or its subfolders, map it to type &#8220;invoice_document&#8221;</li>
<li>For type &#8220;po_document&#8221;, parse the PO number from the <em>object_name</em> and put it into <em>po_number</em>
        </li>
<li>For type &#8220;invoice_document&#8221;, parse the invoice number from the <em>object_name</em> and put it into <em>invoice_number</em>
        </li>
<li>Parse the year from <em>contract_date</em> and put it into <em>fiscal_year</em>
        </li>
<li>Put all POs into a subfolder under /Acme/POs based on their fiscal_year value (i.e., /Acme/POs/2007).</li>
<li>Put all Invoices into a subfolder under /Acme/Invoices based on their fiscal_year value (i.e., /Acme/Invoices/2007).</li>
</ul>
<p>Acme enters these rules into Workbench and runs the migration.  However, after the users see their data in the target repository, they discover a number of issues with the migrated documents.  Below is a description of these issues and how Acme is able to quickly and easily resolve them.</p>
<p>
        <strong>Problem 1: Missing PO Documents</strong>
    </p>
<p>The first issue discovered is that there are not nearly as many POs in the target system as the business users expected to see.  After looking back at the source system, Acme realizes that some POs were mistakenly filed in another folder called /Acme/Purchasing/POs.</p>
<p>If Acme were using a traditional ETL tool, fixing this issue would require defining an additional batch for the newly discovered folder, configuring attribute transformations for the new batch, then executing the new batch.  The difficulty with this approach is that the new batch definitions will overlap with older batch definitions, causing documents to be unnecessarily migrated twice.</p>
<p>
        <strong>Solution</strong>
    </p>
<p>Workbench makes resolving this problem this simple.  The migration analyst simply adjusts the existing rule to also include the newly discovered folder:</p>
<ul>
<li>If the document exists in the /Acme/POs folder or its subfolders, <strong>or /Acme/Purchasing/POs or its subfolders</strong>, map it to type &#8220;po_document&#8221;</li>
</ul>
<div align="center">
        <img src="/article-assets/images/using_mwb_fig3_folders_demo.jpg" border="0" alt="Fig. 3: Graphic of Acme Users Discovering Missing PO Documents">
<p class="figure">
            <b><br />
              Figure 3:<br />
            </b> Discovering the Missing PO Documents</p>
</p></div>
<p>By that one simple rule modification, Workbench now knows to also look for POs in the /Acme/Purchasing folder and will identify the additional documents that are impacted.  The incremental migration feature ensures that only those newly discovered documents are moved, and  rules-based mappings mean that all the additional attribute transformations will be applied to the new documents just as they are for the first set of migrated documents.</p>
<p>
        <strong>Problem 2: Additional Missing PO Documents</strong>
    </p>
<p>Although adding the additional folder corrected some of the missing files, Acme users think there are still more POs to migrate.  The team discovers that during a previous summer, an intern had filed a number of documents somewhat randomly throughout the Finance Department&#8217;s folder structure.  But he did at least apply the naming convention of starting all file names with the PO number.  As in the example above, if an ETL tool were employed, a new batch would need to be defined, mappings replicated for the new batch, and due diligence performed to make sure no documents are duplicated.</p>
<p>
        <strong>Solution</strong>
    </p>
<p>Using Workbench, this issue can be resolved by updating one simple rule.  The migration analyst updates the mapping rule as follows:</p>
<ul>
<li>If the document exists in the /Acme/POs folder or its subfolders, or /Acme/Purchasing/POs or its subfolders, <strong>or is owned by the intern and the object_name starts with &#8220;PO&#8221;</strong>, map it to type &#8220;po_document&#8221;</li>
</ul>
<div align="center">
        <img src="/article-assets/images/using_mwb_fig4_folders_demo.jpg" border="0" alt="Fig. 4: Graphic of Acme Users Discovering Additional Missing PO Documents">
<p class="figure">
            <b><br />
              Figure 4:<br />
            </b> Discovering the Additional Missing PO Documents</p>
</p></div>
<p>When this updated rule is applied, the missing POs show up in the target.  But something unexpected happened &#8211; Workbench marked them as being &#8220;partially&#8221; imported.  This is because the intern is not a valid user in the new system and can&#8217;t be assigned as the documents&#8217; owner.  In this case Workbench will migrate the document, assign a default owner, identify the issue for resolution, and continue processing.  The migration team notes the documents that were partially migrated and adds a rule to map the documents owned by the intern to a valid user.  Then on the next iteration Workbench sees the updated rule and migrates the document again, this time completing the import.</p>
<p>
        <strong>Problem 3: Users Delete Documents in the Source</strong>
    </p>
<p>For business reasons, Acme must keep the source system live during the migration process.    While the Acme migration team is performing the migration, users delete several documents from the source system.  Using traditional migration approaches, there is no easy way to keep the target system in synch with changes made in the source.</p>
<p>
        <strong>Solution</strong>
    </p>
<p>Live-to-Live migrations are possible with Workbench&#8217;s incremental migration and history features.  Each time the tool runs, it identifies documents that have been added, updated, or deleted since the last execution.  Then it performs the necessary functions on the impacted documents automatically &#8211; adding new documents, updating changed documents, creating new versions, or deleting documents as necessary.  In Figure 5 below, see how Migration Workbench identifies the documents deleted during the migration and removes these documents from the target repository.</p>
<div align="center">
        <img src="/article-assets/images/using_mwb_fig5_folders_demo.jpg" border="0" alt="Fig. 5: Graphic of Acme Users Deleting Documents in the Source">
<p class="figure">
            <b><br />
              Figure 5:<br />
            </b> Users Delete Documents in the Source</p>
</p></div>
<p>Workbench also provides the ability to have total visibility into the life of each document passing through the migration process.  This helps users understand which documents have migrated and which ones have not.  More importantly it can record why a document might not have been migrated.  If a rule excludes a document from being migrated Workbench will record why.</p>
<p>
        <strong>Problem 4: Some POs are More Critical than Others</strong>
    </p>
<p>Acme has a critical need to get the POs associated with the current year into the new system in order to meet internal reporting requirements.  Because of the large number of documents in the system, they estimate that migrating the entire repository will cause them to miss this deadline.</p>
<p>With traditional migration approaches it is very difficult to migrate one subset of documents and make it available in the target while continuing to migrate additional lower priority documents.</p>
<p>
        <strong>Solution</strong>
    </p>
<p>Workbench&#8217;s Dynamic Cutover feature anticipates this problem and makes it easy to cut over content based on the users&#8217; schedule.  As Workbench migrates documents into a target system it uses repository-specific permissions (i.e., ACLs in Documentum) to make the documents invisible to the general user population, but visible to the test team to perform quality assurance.   Based on the quality of the data and how quickly the data needs to be in the target the user can define the criteria that identify high priority documents and assign an appropriate cutover schedule.</p>
<p>In Acme&#8217;s case the analyst can add a rule stating all documents with <em>fiscal_year</em> equal to the current year should be set to be cutover much sooner than the rest of the documents.</p>
<ul>
<li>If the <em>fiscal_year</em> is 2008, then set cutover priority to high.</li>
</ul>
<p>When Workbench cuts a document over, it changes permissions on the document in the source repository so that all users can no longer access the document.  At the same time, it updates the permissions on the document so that it is accessible in the target.</p>
<div align="center">
        <img src="/article-assets/images/using_mwb_fig6_folders_demo.jpg" border="0" alt="Fig. 6: Graphic of Cutover">
<p class="figure">
            <b><br />
              Figure 6:<br />
            </b> Some POs are More Critical than Others</p>
</p></div>
<h3>
        <a name="head4" class="section">Conclusion</a><br />
    </h3>
<p>If you found yourself out on the ledge after reading my previous article about the many problems encountered during a typical migration, I hope reading this has talked you back in!  Here at Blue Fish, we&#8217;ve been working hard to create an approach and tool designed to overcome those problems and tame even the most complex migrations.  I&#8217;ve introduced a few of the important points here.  If these have caught your interest, please give us a <a href="/about/contact.php">call</a> or request an evaluation of Migration Workbench.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/using-migration-workbench/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Webinar: Information Access</title>
		<link>http://www.bluefishgroup.com/2008/information-access-webinar-recordings/</link>
		<comments>http://www.bluefishgroup.com/2008/information-access-webinar-recordings/#comments</comments>
		<pubDate>Fri, 11 Apr 2008 13:23:15 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Webinars]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/2008/information-access-webinar-recordings/</guid>
		<description><![CDATA[Last week, wecompleted a four-part Webinar series highlighting some of our recent Information Access projects with organizations like Dell, the University of Leeds, and the federal government. If you&#8217;re wondering what information access is all about, we&#8217;ve got recordings of these webinars online. One of the webinars features yours truly giving a demonstration of FishFinder, [...]]]></description>
				<content:encoded><![CDATA[<p>Last week, wecompleted a four-part Webinar series highlighting some of our recent Information Access projects with organizations like <b>Dell</b>, the <b>University of Leeds</b>, and the <b>federal government</b>. If you&#8217;re wondering what information access is all about, we&#8217;ve got <a href="/info-access/webinar-series.php">recordings of these webinars</a> online.</p>
<p>One of the webinars features yours truly giving a <a href="http://breeze76779882.acrobat.com/p63859158/">demonstration of FishFinder</a>, the internal search application we use here at Blue Fish to discover and access important project-related documentation. FishFinder uses the Endeca platform to index all the documents in our Documentum content management system, and because it&#8217;s blindingly fast, gives our consultants near instant access to best practices, sample code, and other information that has been used on previous projects. This makes our teams more effective since they are not reinventing the wheel, and it allows us to complete our projects more quickly and with less risk.</p>
<p>If you&#8217;d like to know more about any of the solutions featured in these webinars, drop me a line (mikey at bluefishgroup.com).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/information-access-webinar-recordings/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Maybe Google Search Appliance is More Googley Than I Thought</title>
		<link>http://www.bluefishgroup.com/2008/maybe-google-search-appliance-is-more-googley-than-i-thought/</link>
		<comments>http://www.bluefishgroup.com/2008/maybe-google-search-appliance-is-more-googley-than-i-thought/#comments</comments>
		<pubDate>Thu, 10 Apr 2008 19:16:29 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/2008/maybe-google-search-appliance-is-more-googley-than-i-thought/</guid>
		<description><![CDATA[I may have to eat a little bit of crow here. Recently, I made a point that Google Search Appliance (GSA) wasn&#8217;t very innovative, and therefore wasn&#8217;t very &#8220;Googely&#8221;. I still stand by the core of my opinion, which has to do with the way that Google presents search results. Because it can&#8217;t leverage the [...]]]></description>
				<content:encoded><![CDATA[<p>I may have to eat a little bit of crow here. Recently, <a href="/library/2007/why-googles-search-appliance-is-un-googley/">I made a point</a> that Google Search Appliance (GSA) wasn&#8217;t very innovative, and therefore wasn&#8217;t very &#8220;Googely&#8221;. I still stand by the core of my opinion, which has to do with the way that Google presents search results. Because it can&#8217;t leverage the PageRank algorithm that they use on google.com, the search appliance is left to use the same relevance algorithms that other search engines use &#8211; noting the frequency and placement of the search term within the document and using that to determine how relevant the document is for the current search.</p>
<p>But there is more innovation in the Google Search Appliance than I thought there was. Dan Burton, a consultant here at Blue Fish, recently wrote an <a href="http://www.bluefishgroup.com/library/2008/google-enterprise-search-appliance-overview/">overview of the Google Search Appliance</a>, and I learned a few things I didn&#8217;t previously know. One innovative technique they use is called KeyMatch, and it allows certain users to promote or highlight key content for a given search term. Similar to the way that Google Ads work on google.com, KeyMatch lets a user with the right permissions highlight a document, moving it to the top of the search results. If used correctly, KeyMatch can help companies satisfy their user&#8217;s most frequent searches by manually placing the most relevant result where they will easily see it. That&#8217;s pretty Googley.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/maybe-google-search-appliance-is-more-googley-than-i-thought/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New Batch of Articles</title>
		<link>http://www.bluefishgroup.com/2008/new-batch-of-articles/</link>
		<comments>http://www.bluefishgroup.com/2008/new-batch-of-articles/#comments</comments>
		<pubDate>Wed, 09 Apr 2008 18:55:42 +0000</pubDate>
		<dc:creator>Michael Trafton</dc:creator>
				<category><![CDATA[Blog]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/2008/new-batch-of-articles/</guid>
		<description><![CDATA[The team has been busy lately, cooking up a tasty new batch of articles. These articles cover a range of topics from nuts and bolts programming with Documentum lifecycles and search APIs to guidance on how to deploy enterprise technology across multiple business units. There are also a couple of articles about search and information [...]]]></description>
				<content:encoded><![CDATA[<p>The team has been busy lately, cooking up a tasty new batch of articles. These articles cover a range of topics from nuts and bolts programming with Documentum lifecycles and search APIs to guidance on how to deploy enterprise technology across multiple business units. There are also a couple of articles about search and information access &#8211; one is on Google&#8217;s Enterprise Search Appliance and the other is about simplifying the deployment of Endeca&#8217;s information access platform.</p>
<ul>
<li><a href="/library/2008/dfc-search-in-depth/">DFC Search in Depth</a> &#8211; Aaron has written a great article that explains how to use the DFC search APIs to query Documentum and process the results.</li>
<li><a href="/library/2008/google-enterprise-search-appliance-overview/">Google Enterprise Search Appliance Overview</a> &#8211; This article covers the features of Google&#8217;s search appliance and how it compares to other solutions on the market.</li>
<li><a href="/library/2008/custom-java-lifecycle-modules/">Custom Java Lifecycle Modules</a> &#8211; Explains how to insert custom business logic into Documentum lifecycle state transitions.</li>
<li><a href="/library/2008/initiating-an-im-program-across-a-multi-business-enterprise/">Initiating an IM Program Across Multiple Business Units</a> &#8211; Bryant explains how he&#8217;s been successful in the past when he&#8217;s had to deploy enterprise software across multiple business units or divisions.</li>
<li><a href="/library/2008/simplifying-endeca-deployments/">Simplifying Endeca Deployments with the Deployment Template</a> &#8211; Until recently, deploying Endeca has been a bit of a black art. Learn how to make Endeca deployments easier with deployment templates.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/new-batch-of-articles/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Initiating an IM Program across a Multi-Business Enterprise</title>
		<link>http://www.bluefishgroup.com/2008/initiating-an-im-program-across-a-multi-business-enterprise/</link>
		<comments>http://www.bluefishgroup.com/2008/initiating-an-im-program-across-a-multi-business-enterprise/#comments</comments>
		<pubDate>Tue, 08 Apr 2008 11:00:00 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Custom ECM Solutions]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/2008/initiating-an-im-program-across-a-multi-business-enterprise/</guid>
		<description><![CDATA[Introduction There is an old adage regarding how you eat an elephant&#8230;one bite at a time. This saying is true about many things in life that present us with significant challenges and can be especially true in the business world. Let me share with you one particular challenge that you may be facing &#8211; initiating [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Introduction</a><br />
    </h3>
<p>There is an old adage regarding how you eat an elephant&#8230;one bite at a time.  This saying is true about many things in life that present us with significant challenges and can be especially true in the business world.  Let me share with you one particular challenge that you may be facing &#8211; initiating a program of Information Management work across a huge business or multiple business units.</p>
<p>I have been fortunate or depending on your perspective, rather unfortunate to create and lead technology programs throughout my career, and I have learned a few things about how to launch IT programs.  This article will help you understand the typical challenges that organizations face in initiating a program of work and will give you practical recommendations and approaches to overcoming those challenges.  Although this article is focused on information management, you should be able to apply the findings to other IT domains.</p>
<h3>
        <a name="head2" class="section">Challenges Facing Organizations when Initiating an IM Program</a><br />
    </h3>
<p>As we talk about the many challenges that one faces when initiating an IM program, the biggest obstacle is the lack of maturity in the organization to execute a series of IT projects focused on specific objectives.  There is a common saying that Rome was not built in a day, and the same can be said about creating a successful IM program. You have to &#8220;earn the right&#8221; to run a program within your organization by building up credibility that you can deliver true value; unfortunately, significant value typically does not come to the organization until a significant percentage of the program is complete. This is the typical chicken and egg conundrum.</p>
<p>As you can see from Figure 1, the maturity path to program success starts out with little or no action or success (typically in pilot mode) followed by one-off successes (individual, ad-hoc projects) and culminating into a decision to manage work in a program with the hopes of being extremely successful.  The goal of the organization should be to accelerate through the maturity curve to realize the highest enterprise value as quickly as possible.</p>
<div align="center">
        <img src="/article-assets/images/maturity-path-to-program-success.png" border="0" alt="Fig. 1: Maturity Path to Program Success">
<p class="figure">
            <b><br />
              Figure 1:<br />
            </b> Maturity Path to Program Success</p>
</p></div>
<p>In fact, the ideal path forward would be to skip Bite 2 and go directly to Bite 3 from Bite 1.  I have seen and read about organizations that have been successful in doing this.  For example, while earning my Masters Degree at the W.P. Carey School of Business (Arizona State University), I had the opportunity to examine a case study about Cisco and its CIO, Peter Solvik, who did just that.  When Solvik was hired by Cisco&#8217;s CEO John Chambers in 1993, he looked into Cisco&#8217;s business and IT environment and identified two major challenges:</p>
<ol>
<li>The IT Department was viewed as a cost center that reported through the Finance department</li>
<li>The current systems could not support Cisco&#8217;s current value chain or projected business growth</li>
</ol>
<p>To address the second challenge he proposed a $15 million ERP program focused on standardizing and driving flexibility within Cisco&#8217;s information systems.  He chose to jump straight to Bite 3 (from Bite 1) and bet his career on the success of the ERP program.  The program was a huge success.  When Cisco later standardized and reorganized R&amp;D and marketing from multiple business units to three lines of business, the ERP system allowed them to complete all reorganization changes in less than 60 days for a cost less than $1 million.</p>
<p>If you are fortunate enough to have the sponsorship, authority, and execution skills to jump straight to Bite 3 (like Solvik), then, by all means do so; otherwise, you will need to take an intermediate step (Bite 2).  I&#8217;ll discuss each bite in a little more detail.</p>
<h3>
        <a name="head3" class="section">Bite 1: Minimal Success</a><br />
    </h3>
<p>During the first bite, most company leaders are not concerned with, or have even thought of implementing a IT solution within a program framework.  They are typically in fact-finding mode and wear the hat of &#8220;early adopter&#8221;.  Their focus is on learning about a new technology or methodology, and conducting pilot projects looking to get that new edge in operations.  Usually, there is not much focus by a centralized corporate IT standards group to assist with the effort.  In fact, there may not even be a centralized corporate IT group assembled when leaders begin the journey.  During this phase, leaders can be thought of as mad scientists trying to find a great new secret that is going to elevate the business to new heights.  Think of it as going to the driving range and hitting balls with a new golf grip, just tinkering out the new grip on the range to see if you can hit the ball straight before thinking about using the new grip on the course.</p>
<div align="center">
        <img src="/article-assets/images/minimal-success.png" border="0" alt="Fig. 2: Minimal Success">
<p class="figure">
            <b><br />
              Figure 2:<br />
            </b> Minimal Success</p>
</p></div>
<p>If the pilot project(s) prove to be successful, company leaders will become evangelists within their organizations and look for additional opportunities to achieve similar success &#8211; this is Bite #2.  This path to adoption is opportunistic at best and typically occurs in a reactive manner.  In large organizations, adoption opportunities are often found in sister companies within the same product group or with other business units in the same region as the previous pilot project(s).  There are many positives and negatives that leaders will encounter.  On the positive side, value is generated within the enterprise with the successful deployment of each IM solution, and hopefully the result is increased end user efficiency and hard dollar savings.  On the negative side, the adoption of stand-alone &#8220;one off&#8221; solutions drives up the total cost of ownership (TCO) in delivering and supporting the pointed solutions.  Every solution implementation ends up being a different instance that drives up costs and reduces the overall benefit.  Returning to our golf grip analogy, Bite 2 is taking the new grip on the course and using it sporadically &#8211; hitting some really great golf shots that set you up for birdie and then hitting some disastrous shots, setting yourself up for triple bogey.</p>
<div align="center">
        <img src="/article-assets/images/one-off-success.png" border="0" alt="Fig. 3: One-Off Success">
<p class="figure">
            <b><br />
              Figure 3:<br />
            </b> One-Off Success</p>
</p></div>
<p>At this point, leaders are faced with a crossroads.  Do they continue in a one-off manner, or do they work to standardize to reduce TCO?  Back to my golf analogy, do you use the golf grip for every shot and practice to make our shots more consistent or do you constantly change our grip for each shot and continue to spray the ball around the course?</p>
<p>The centralized corporate IT group often comes into the equation at this stage and starts to understand the new technology / method and decides how best to manage it within its current standards portfolio.  This is a good thing, and you need to embrace the group and leverage them to help you with your upcoming challenges.</p>
<p>When taking Bite 3, some of the challenges you are going to need to address include: How do you address and manage a broad stakeholder community, scope of work, and unique set of business unit requirements within a single program?  Can value truly be created by deploying a common IM solution across a multi-business organization?  How do you deal with the unique business operations that provide significant competitive advantage?  How do you deal with other business priorities that may be of similar or higher priority than your specific program?  Also, how do you incorporate and align the previous and current &#8220;one-off&#8221; initiatives that were launched during Bite 2? Finally and perhaps most importantly, how do you kickoff the program and jump in with both feet&#8230;actually take Bite 3?</p>
<h3>
        <a name="head4" class="section">Approach to Overcoming Challenges (and Taking Bite 3)</a><br />
    </h3>
<p>The first step in taking Bite 3 is to identify and assemble the steering committee that is going to help endorse and evangelize the effort to initiate the IM program.  I like to call this team my &#8220;executive swat team of change agents&#8221;.  They are the critical executives (and your closest advisers and hopefully friends) within each of the company&#8217;s business units. They have a vested interest in lowering TCO, increasing adoption rates, and increasing quality of current and future IM initiatives.  Some of these trusted advisers may have already implemented solutions during the Bite 1 or Bite 2 phases and may even have scars from the previous implementation (we can use these scars to our advantage as you will see later).</p>
<p>You are probably asking yourself, &#8220;How can they spare time to actively participate in this program?&#8221; and &#8220;How do I know I&#8217;ve identified the right person(s)?&#8221;  You must ask yourself whether each selected member is personally accountable for driving increased value by leveraging information management and whether the member is a great evangelist within his/her business unit.  If you can answer yes to both of those questions, you have probably &#8220;found your huckleberry&#8221;.  Now, how do you get them to invest time in establishing a program?  You use their previous one-off successes, scars, and upcoming initiatives to convey the value proposition for their participation in the program.  Point out the future opportunity to reduce TCO and improve user adoption within their business unit.  As you are assembling the team, be sure you do so in a very efficient manner.  You can bet your trusted advisors have many other priorities (or fires) in their purview so you must be extremely careful not to abuse their time.  Hold timely, high impact, high value meetings or workshops to initiate the formation of the program.</p>
<p>Once you have assembled your steering committee the next step is to develop the program&#8217;s initial guiding principles and overarching objectives and gain a common understanding of the current state of each participating business unit&#8217;s IM program.  Often the most efficient way of doing this is to hold an inaugural workshop introducing the steering committee members and then lead facilitated sessions to identify the program&#8217;s guiding principles and objectives.  It is during this initial workshop that you want to focus on driving a high level of effectiveness with the steering committee &#8211;  accelerating them through the typical group effectiveness stages and taking them through the forming, storming, and norming stages to a performing execution level.  Finally, it is extremely important to allow time to identify the current IM priorities for each steering committee member and provide an opportunity for them to share their current IM roadmaps.</p>
<p>Following the establishment of the guiding principles and program objectives, your next focus should be to educate the steering committee on and gain their agreement for the target domain area of focus for the program.  More than likely the steering committee members will have varying levels of maturity and knowledge of the target domain, so you may have to conduct education / orientation sessions to get the members to the same level of understanding.  An effective way of doing this is to conduct demonstrations of the solutions that have already been built during Bite 2 (the &#8220;one-off&#8221; successes).  This is a great way to get your steering committee engaged by having them lead the demonstrations!  Additionally, lessons learned from the previous projects need to be highlighted during the demonstrations and incorporated into the program framework.</p>
<p>As you educate the steering committee on the domain area, the next move is to work with them to decide on the high level domain scope.  For starters, look to leverage the recent one-off successes (pilots and quick wins) to accelerate the program scope identification.  This may be 75 &#8211; 80% of the answer.  From there, look at the upcoming IM priorities of the participating business units and derive the scope by integrating the two findings.  It may be necessary to segment the scope into logical areas.  If this is the case, try to segment into no more than 3-5 sub areas.</p>
<p>Once you have identified the program scope you are on your way to launching your program.  The final two steps include establishing near-term achievement milestones for the program and developing a business case for funding approval.  I like to structure the milestones around user adoption goals.  Start out by developing a chart that spans 2-4 years along the horizontal axis and the scope down the vertical axis.  Working with your steering committee, plot the IM program&#8217;s user adoption milestones on the graph and obtain approval from the members.  This milestone chart will form the foundation of your program and will assist in scheduling projects within the program to achieve the desired objectives.  A sample of a milestone chart is below.</p>
<div align="center">
        <img src="/article-assets/images/im-program-milestone.png" border="0" alt="Fig. 4: IM Program Milestone Chart">
<p class="figure">
            <b><br />
              Figure 4:<br />
            </b> IM Program Milestone Chart</p>
</p></div>
<p>Once all are in agreement on the key milestones for the IM program, you need to complete one final step prior to taking Bite 3 &#8211; getting approval on the business case.  I have seen some really great business cases and some really poor business cases.  In my opinion, the best ones have a few things in common.  First they are simple: simple to read, simple to understand, and simple to get approval (because of the quality).  Second, the business case must take care of the basic &#8220;blocking and tackling&#8221;.  This includes a great value proposition, a financial analysis projecting a lower TCO (if you properly planned), and a plan for mitigating any risks you may have identified during this process.  Third (and most importantly), the business case needs to focus on how you will ultimately enhance the end user&#8217;s work activities (and life) by delivering high value through the IM program.  If you can&#8217;t foresee effective end user improvements with the IM program, it is not worth pursuing.</p>
<p>Finally, let&#8217;s take a look at how life will be for you as you gain approval on the business case and take Bite 3.  The first change you will see is that your evangelistic activities will slightly diminish and your role will become more of a governor &#8211; overseeing and managing the IM program.  Secondly, you will finally be &#8220;ahead of the train&#8221; instead of behind it running trying to chase it.  Your projects will be proactively planned, managed, and well organized.  Finally, if executed correctly, your organization will reap heaps of value and benefit that would not have been possible during Bite 1 and Bite 2.</p>
<div align="center">
        <img src="/article-assets/images/program-success.png" border="0" alt="Fig. 5: Program Success">
<p class="figure">
            <b><br />
              Figure 5:<br />
            </b> Program Success</p>
</p></div>
<p>So what is next? It is time to leverage the framework you&#8217;ve just learned and start taking down the elephant.  Going back to our golf analogy, it is time to use your new golf grip for every single shot until it becomes natural.  You may have a few misses as you navigate around course, but in the long run your golf game (and the value to your company) will significantly improve.  Go get it&#8230;good luck on the course!</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/initiating-an-im-program-across-a-multi-business-enterprise/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Google Enterprise Search Appliance Overview</title>
		<link>http://www.bluefishgroup.com/2008/google-enterprise-search-appliance-overview/</link>
		<comments>http://www.bluefishgroup.com/2008/google-enterprise-search-appliance-overview/#comments</comments>
		<pubDate>Tue, 08 Apr 2008 11:00:00 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Information Access]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/2008/google-enterprise-search-appliance-overview/</guid>
		<description><![CDATA[Introduction If you&#8217;re reading this article, chances are pretty good you&#8217;re familiar with Google. You may even have used it to find this article. Over the past decade, Google has established itself as the most widely used web search engine, and we all know that when we&#8217;re looking for something on the web, we start [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Introduction</a><br />
    </h3>
<p>If you&#8217;re reading this article, chances are pretty good you&#8217;re familiar with Google.  You may even have used it to find this article.  Over the past decade, Google has established itself as the most widely used web search engine, and we all know that when we&#8217;re looking for something on the web, we start with Google.  It has become such a pervasive part of our web experience that we even use &#8216;google&#8217; as a verb (both the Oxford English Dictionary<well_formed_html><br />
            <sup><a href="#references" name="footnote_1">1</a></sup><br />
        </well_formed_html> and Merriam-Webster<well_formed_html><br />
            <sup><a href="#references" name="footnote_2">2</a></sup><br />
        </well_formed_html> authoritatively incorporated &#8216;google&#8217; as part of the English language in 2006).</p>
<p>What you may not be as familiar with are Google&#8217;s enterprise offerings.  Google says that their mission is &#8220;to organize the world&#8217;s information and make it universally accessible and useful.&#8221;<well_formed_html><br />
            <sup><a href="#references" name="footnote_3">3</a></sup><br />
        </well_formed_html>  The World Wide Web obviously represents a huge portion of the world&#8217;s information, but it is by no means all of it.  Much more information is locked away behind corporate firewalls, residing in documents on file shares, tucked away deep inside content management systems and source control systems, embedded in databases, and hidden in all manner of other places.  But how do you organize it and make it accessible and useful?  Google&#8217;s answer to this problem is what they call &#8220;Google Enterprise&#8221; and the &#8220;Google Search Appliance&#8221; (GSA).  So what does a Google Search Appliance provide?  What&#8217;s missing?  How does it work?  And is a Google Search Appliance the right choice for your enterprise search needs?</p>
<h3>
        <a name="head1" class="section">A Closer Look</a><br />
    </h3>
<h4>The Power of the Google Name</h4>
<p>There are a number of reasons you may be interested in a Google Search Appliance to tackle your enterprise search problems.  Not the least of which is the Google brand.  Google has made a name for itself as the premier web search engine, and years of using Google has made users comfortable with the way Google works.  They are accustomed to the way it looks and feels, and they are highly trusting in the results they receive.  If introducing a different tool might be jarring to your users, this is an element that is not to be discounted.</p>
<p>Google also commands an impressive engineering department that is hard at work improving search algorithms and developing toolkits to leverage the latest technologies.  They are masters at leveraging the open source community to further speed development efforts.  While the core algorithms of what makes Google tick are kept tightly under wraps, the interfaces used to manipulate Google and many of its associated components (Google Maps, Google Calendar, etc.) are opened up to the world to encourage forward development by a broader community.</p>
<h4>Search as an Appliance</h4>
<p>One differentiating factor that you have probably already figured out for yourself is that the Google Search Appliance is an appliance. By combining a hardware and software solution (the GSA runs a special in-house flavor of Linux called &#8216;Google Linux&#8217;), Google has locked down the control points to improve ease of installation and configuration.  This also gives them the opportunity to highly optimize and tune their system, in contrast to the broader platform support that some other search vendors provide.</p>
<p>When you set up one of these appliances (a rack-mount box with a bright yellow swiss-cheese motif), you are presented with the minimal set of configuration options needed to get up and running.  Configuration is all accomplished through a straight-forward web interface, and it&#8217;s almost trivial to point it at your intranet or file shares to being crawling and indexing content right away.</p>
<p>The extreme degree of standardization inherent in an appliance deployment model has other advantages as well.  Multiple GSAs can be &#8220;chained&#8221; together for increased capacity and performance with minimal configuration.  Updates can be reliably retrieved by the appliance with little worry about version conflicts or platform quirks.  Troubleshooting can be greatly simplified by removing a multitude of variables that might be available in an environment where hardware, operating system, and software come from multiple different vendors.</p>
<p>This approach also has its drawbacks, however.  The search algorithms used by the appliance can&#8217;t readily be tuned if the need arises, and deployments requiring any significant customization can become more cumbersome.</p>
<h4>Crawling and Indexing Content</h4>
<p>Crawling and extracting content from websites both internal and external is supported out-of-the-box.  So is crawling file systems and querying SQL databases, and these are all easily configurable through the GSA&#8217;s configuration web interface.  However, this may only cover a small fraction of business information within an organization.</p>
<p>Many organizations have large numbers of critical documents in other places that they need to search.  These documents might reside in content management systems such as Documentum or FileNet.  They might reside in source control systems like CVS or Subversion.  They might also reside in collaboration systems such as eRoom or SharePoint, or elsewhere.  For these types of additional content repositories, Google provides a connector framework that can be used to connect to them and extract content.  The connector framework provides out-of-the-box support for Documentum, FileNet, SharePoint, and LiveLink  Additional connectors for other systems, or those providing advanced functionality, are available from 3rd party developers (from costs ranging from free to tens of thousands of dollars).  Connectors can also be custom-built if necessary for obscure or home-grown systems that house important content.</p>
<p>These connectors, however, require their own application servers to run, and can&#8217;t reside on the appliance itself.  In a large, heterogeneous enterprise environment, the cost and work involved in setting up and maintaining a large number of connectors may become a significant amount of overhead that can undermine the value provided by a consolidated search interface.</p>
<p>Google Enterprise can extract and index content from over 200 document formats, leveraging the Oracle (formerly Stellent) libraries for extracting content from obscure document formats.  The supported list is about what you would expect, encompassing most standard text, markup, image, word-processing, spreadsheet, presentation, and database types, along with a myriad of others.  Conspicuously missing currently is support for Office 2007 documents, although I&#8217;ve been assured that&#8217;s coming in an update in the next few months.</p>
<h4>Serving Up Results</h4>
<div align="center">
        <img src="/article-assets/images/GSA_Interface.png" border="0" alt="Fig. 1: Google Enterprise Interface">
<p class="figure">
            <b><br />
              Figure 1:<br />
            </b> Google Enterprise Interface</p>
</p></div>
<p>The GSA provides an out-of-the-box search interface that is about as close to google.com as you can get.<well_formed_html><br />
            <sup><a href="#references" name="footnote_4">4</a></sup><br />
        </well_formed_html>  For anyone who has used google.com, the organization, layout, and style will be extremely familiar and instantly usable.  For those customers wishing to customize the look and feel of their search results, the interface can be adjusted using a set of templates and style sheets to provide a customized look and feel.  The search results information can also be returned as raw XML, which can be useful if you are trying to integrate the results powered by the GSA into another application within your enterprise.</p>
<p>Reporting comes standard as well.  Out-of-the-box reports provide administrators visibility into what searches are being performed, and this data can be sliced across data sets, time, user identity, and search terms.  You can also see how the results fared against the users queries.  How many users clicked on the top result?  How many clicked on the 2nd?  How many had to click down to the next page? And so forth.</p>
<h3>
        <a name="head1" class="section">The Right Results</a><br />
    </h3>
<p>All the previous points aside, what you really want to know is whether a Google Search Appliance will help your users find the information that they are looking for.</p>
<h4>Why PageRank isn&#8217;t Enough</h4>
<p>Google has built their name and reputation on the success of google.com and its sometimes uncanny ability to find the most useful, relevant results &#8211; the ones you&#8217;re looking for.  One of the primary ideas behind the relevance ranking scheme is a patented algorithm known as PageRank.<well_formed_html><br />
            <sup><a href="#references" name="footnote_5">5</a></sup><br />
        </well_formed_html>  This leverages the vast, interconnected nature of the web to judge an individual page&#8217;s importance based on how, and how often, it is linked to by other pages.  The basic idea is that the more often authoritative pages link to a page, the more authoritative that page itself is.</p>
<p>This works like a charm in the context of the World Wide Web, but behind the firewall of an organization, the picture is likely to be very different.  Documents that reside on a file share, or in a content management system, don&#8217;t generally link to one another.  So there is no vast, interconnected web to leverage.  The content of documents and their metadata may be the only pieces of information available to a search engine, and in many cases, that metadata may be extremely sparse.</p>
<h4>Beyond PageRank</h4>
<p>The smart folks over at Google, who recognize that what works for web search doesn&#8217;t necessarily work for enterprise search, have been busily writing more capable algorithms to handle the problems inherent in the enterprise search space.  A not-so-quick look through Google&#8217;s many filed patents shows more than a few that are clearly targeted towards the complexities of enterprise search, such as &#8220;Methods and Systems for Determining a Meaning of a Document to Match the Document to Content&#8221; or &#8220;Method and Apparatus for Characterizing Documents Based on Clusters of Words&#8221;.  These are just a couple examples.<well_formed_html><br />
            <sup><a href="#references" name="footnote_6">6</a></sup><br />
        </well_formed_html>
    </p>
<p>The Google Search Appliance leverages &#8220;hundreds of factors, only one of which is PageRank&#8221;<well_formed_html><br />
            <sup><a href="#references" name="footnote_7">7</a></sup><br />
        </well_formed_html> to ultimately rank results and return them to the user.  These take into account not only literal document content, but also document structure, format, source, age, and other metadata.  Google prides itself on the fact that this combination of advance ranking techniques provides high quality out-of-the-box relevance ranking, on par with the quality of results users are accustomed to getting from google.com.</p>
<p>I have yet to see a detailed and unbiased &#8220;search-off&#8221; between various competitors in the enterprise search space. (Perhaps if I can accumulate enough free time in the future, I may attempt something like this myself.)  As such, it&#8217;s difficult to say how the out-of-the box results relevance of the Google Enterprise solution really stacks up against the competition.  Google claims as many success stories as any other search solution provider, and the reality is that because the organization of information within different enterprises can vary so drastically, some search algorithms may simply work better for some data than others.</p>
<h4>(Almost) No Tuning Allowed</h4>
<p>Google is so confident in their results relevance that they (unlike many competitors) do not provide much configuration or tooling for tuning search results.  Even if the out-of-the-box results from a GSA work very well for many situations, when they fall short, there&#8217;s not much recourse.  Tuning can be a key element of a successful search solution, especially within enterprises where years of cultural evolution of how knowledge is handled may make for unusual conventions or organizational schemes that could easily skew the results of a search system that doesn&#8217;t understand them.  If, for example, a particular custom piece of metadata is critical to the organization of data within your enterprise, a system would need to recognize that piece of metadata and be able to present it to the users in order to be most effective.</p>
<p>One method of tuning that is available is &#8216;source biasing&#8217;.  This allows an administrator to specify that results from a particular source (say, a well-controlled content management system) be regarded as more authoritative than those from other sources (say, an informal wiki page).</p>
<p>You can also define synonyms as part of the system configuration, and these synonyms can be configured to either be automatically included as part of the search itself, or simply to provide the user with search suggestions. For example, if a user enters &#8216;SOP&#8217; as their search term, the system could search for both &#8216;SOP&#8217; and &#8216;standard operating procedure&#8217; under the covers, or alternately, suggest &#8220;did you mean &#8216;standard operating procedure&#8217;?&#8221; depending on configuration.</p>
<h4>Metadata to the Rescue?</h4>
<p>One potential way to alleviate the pitfalls of imperfect (or unknown) relevance quality is to arm users with rich metadata.  When such metadata is available, and the search system understands how to leverage it, users can use this metadata to quickly hone in on what they are after by selecting search refinements driven by this metadata.  Although the Google Search Appliance provides minimal support for retrieving, displaying, and leveraging metadata, it is not a focus area for the product. Contrast this with Endeca, who have mastered the complexities of leveraging rich metadata in a search context.</p>
<p>The GSA capabilities regarding metadata are extremely limited out-of-the-box, but can be augmented by a free set of code provided by Google.<well_formed_html><br />
            <sup><a href="#references" name="footnote_8">8</a></sup><br />
        </well_formed_html> This code, written in JavaScript, integrates tightly with the results returned by a GSA to provide basic parametric query refinement.  This may be sufficient for extremely basic metadata, but soon falls short as the complexity of metadata increases, as it lacks the ability to handle managed taxonomies, ranged queries, or even multi-valued result records, let alone even more advanced and obscure features that might be required in a metadata-rich application.</p>
<p>The problem is that sometimes, the metadata that would be most useful in this context simply doesn&#8217;t exist, or at least, doesn&#8217;t exist reliably.  Few organizations have the content management discipline to ensure that every document on their network is tagged with accurate information about who wrote it, what version it is, which departments it may be relevant for, etc.</p>
<p>Google&#8217;s stance is that since this sort of metadata is generally so unreliable behind the firewall, there&#8217;s little point in going to lengths to drive the search results based on said metadata, and it is instead more advantageous to focus on the default (non-metadata driven) results rankings.  In many cases, this is absolutely true. However, if the information management discipline is mature enough to provide this metadata, it would be an egregious oversight to omit its use from a search solution.</p>
<h3>
        <a name="head1" class="section">What Else is in the Box?</a><br />
    </h3>
<p>Several other features provided by the Google Enterprise are worth mentioning here.  These features bring a little more polished feel to the search solution and, in addition to making it feel &#8220;more like Google&#8221; can bring some interesting and useful tools to the fingertips of your users.  In essence, the goal of all these features is to provide the users with short cuts that allow them to get to what they&#8217;re looking for as quickly and easily as possible.  Note that this is by no means an exhaustive list of current features, and history has shown that as new features enter the Google &#8216;stack&#8217;, Google often makes an effort to incorporate analogous capabilities into the GSA. </p>
<h4>OneBox</h4>
<p>Try going to google.com and entering &#8220;weather&#8221; along with your zip code as the search terms.  The first result that comes back isn&#8217;t exactly a result like the others, but chances are pretty good that it&#8217;s telling you the information that you were after, namely, &#8220;What&#8217;s the weather like in the zip code I entered?&#8221;  This is what Google calls &#8220;OneBox&#8221;, and they have brought it to their enterprise solutions as well.</p>
<p>OneBox works by recognizing patterns in the search terms, and firing off a real-time query to an external system to bring back information.  In the weather example, the information presented above the results is not stored in Google&#8217;s index.  It is harvested at query time from a site that keeps current weather data.</p>
<p>OneBox modules can connect to everything from weather services and stock quotes to salesforce.com installations and company directories.  Here again, Google has provided a framework to enable 3rd parties to create OneBox modules, so the door is open to connect to any system that you think might provide value to your users.  Google hosts a gallery of OneBox modules<well_formed_html><br />
            <sup><a href="#references" name="footnote_9">9</a></sup><br />
        </well_formed_html> that are written by 3rd parties and made available to other GSA users, usually for free.  Many enterprise software vendors, such as Salesforce.com, Cognos, BusinessObjects, and others have published OneBox modules for use with their respective systems.  One particularly slick module allows you to see not just other employee&#8217;s contact information, but also their free/busy schedules via their Exchange calendars.</p>
<h4>Do-It-Yourself Keymatches</h4>
<p>Similar to how google.com displays a couple of sponsored links at the top of the search results for search queries matching certain words, a GSA can display what it calls &#8216;Keymatches&#8217; in the same way.  If you happen to know that a particular document is the authoritative source for a subject in your organization, but it doesn&#8217;t always show up at the top of the search results for certain terms that people may use, you can create a Keymatch for that search term that directs users to the correct document.</p>
<p>You even have the option of opening this Keymatch authoring capability up to other users within your organization, not just administrators.  Users who have some authoritative knowledge about certain information areas within the organization can now become empowered to quickly and easily help steer other users in the direction of the &#8220;right&#8221; information.</p>
<p>Of course, implementing this sort of scheme definitely requires some discipline and trust within your user community.  You can imagine the usability nightmare that could emerge if dozens of users all entered different Keymatches for the same search term!</p>
<h4>Search-As-You-Type</h4>
<p>For certain pieces of information that are searched for most often, Google has provided a facility for users to get the information they&#8217;re after without even finishing their search.  Much like the &#8220;type-ahead&#8221; functionality seen now on many websites, the &#8220;Search-As-You-Type&#8221; feature communicates with the server under the covers to perform queries as you are typing in your request.  For matches that occur against a well-known set of results (say, dictionary definitions, stock quotes, or company directory listings) the results can be shown immediately to the user in a JavaScript pop-up window.</p>
<p>Being able to easily find the phone number or email address of a colleague by simply typing the first few letters of their name can be a huge time saver, especially in an organization with hundreds or thousands of employees.</p>
<h3>
        <a name="head1" class="section">What&#8217;s Missing?</a><br />
    </h3>
<p>For all the slick features that the Google Search Appliance brings to the table, there are some features available from other enterprise search vendors that are notably absent in Google&#8217;s offering.</p>
<p>I&#8217;ve already touched on a couple of these.  Perhaps most notable is the almost non-existent search tuning capability.  Although in many ways search tuning can be a headache unto itself, the lack of any capability for tuning may be a turn-off for some potential customers.  If the out-of-the-box results work well for your data and your users, then you probably don&#8217;t care about any tuning capabilities.  However, if you do need to improve those results, you will miss the tuning capabilities dearly.  And the unfortunate reality is that you may not know which category you fall into until well into the implementation of a particular solution.</p>
<p>Another significant gap is around leveraging rich metadata, as I discussed briefly in the section entitled &#8220;Metadata to the Rescue?&#8221;  Again, this is a situation where, if you don&#8217;t need the metadata capabilities (you may just not have the metadata available to work with), then you won&#8217;t miss them, but if those capabilities will be instrumental in building an effective search solution, their absence will be a deal-breaker.</p>
<p>For organizations looking forward to increased content management discipline and maturity, this may be an especially important factor.  Just because that metadata doesn&#8217;t exist now doesn&#8217;t mean it might not in the future, and when it does exist, it will be important to have the capabilities required to make the most of it.</p>
<p>Another key factor to consider is security integration.  The GSA can integrate with various different security systems, such as LDAP and NTLM, and it can use a variety of authentication methods such as HTTP Basic, HTTPS, x509, and SAML.  However, the GSA is only able to use a late-binding security model.  That is, security credentials are checked for each search result at the time they are returned to the user.  A late-binding model ensures constant security enforcement, but can often be more difficult to implement and less performant than an early-binding model.  It may also require significant integration if secure documents reside in 3rd party repositories, as the GSA must be able to &#8220;ask&#8221; that repository at query time about the security status of particular documents with respect to the user&#8217;s credentials.  This integration can become increasingly complex if multiple different repositories with different security models need to be searched together.</p>
<h3>
        <a name="head1" class="section">Is Google Enterprise Right for Your Enterprise?</a><br />
    </h3>
<p>What much of this boils down to is that the GSA is intended as a &#8220;general-use&#8221; search tool.  After all, it is sold as an appliance.  It is intended to minimize effort and maximize value out-of-the-box.  It is not intended as a platform for building focused, search-based applications.</p>
<p>You should keep in mind the following points when evaluating Google Enterprise as a potential search solution:</p>
<ul>
<li>As an appliance, the GSA provides extremely easy installation, configuration, and update mechanisms.</li>
<li>The dedicated hardware/software solution is highly optimized, and it performs and scales well.</li>
<li>The GSA handles basic content sources with great ease.  Web content, file shares, and relational databases are very easy to set up.  Extracting content from other repositories may require more cost, advanced configuration, hardware, maintenance, or even coding, depending on the particulars.</li>
<li>The GSA has a &#8220;black-box&#8221; set of relevance algorithms, with little to no opportunity to influence results ranking.  The efficacy of the out-of-the-box relevance may vary depending on your data, and although anecdotally is generally quite good, if it doesn&#8217;t work well for you, there is little you can do about it.</li>
<li>The user interface provided by the GSA is familiar and intuitive because of its resemblance to google.com, and can be customized for look and feel as needed.</li>
<li>A number of extras like OneBox and Search-As-You-Type can greatly enhance the search experience, but also may require additional configuration or coding.</li>
<li>Open APIs encourage 3rd party development of additional functionality for the GSA.  A growing library of OneBox modules and content connectors is already available, so you may find that what you need has already been written by someone else.</li>
<li>The metadata handling capabilities of the GSA are very basic, and are simply not geared towards a rich-metadata environment or application.  If you intend to leverage rich metadata as part of your search solution, you may be better off looking for a search platform, rather than a search appliance.</li>
<li>The GSA handles several standard security modes, but is not well-equipped to deal with reconciling multiple security models across different repositories, and does not support an early-binding security model, which is less secure but may be more convenient for some applications.</li>
</ul>
<p>I hope this article has provided some helpful insights into the Google Search Appliance, and some of the relevant aspects to consider.  If you have any questions or comments, I encourage you to comment on this article.</p>
<p>    <well_formed_html><br />
        <a name="references"></a><br />
    </well_formed_html></p>
<h3>
        <a name="head1" class="section">References</a><br />
    </h3>
<ol>
<li>
                <a href="http://web.archive.org/web/20060707062623/http://msnbc.msn.com/id/13720643/" target="_1">MSNBC &#8211; July 5, 2006</a>
            </li>
<li>
                <a href="http://web.archive.org/web/20060710220930/http://www.mercurynews.com/mld/mercurynews/business/14985574.htm" target="_2">San Jose Mercury News &#8211; July 7, 2006</a>
            </li>
<li>
                <a href="http://www.google.com/corporate/" target="_3">Google Corporate Statement</a>
            </li>
<li>
                <a href="http://www.google.com/enterprise/mini/end_user_features.html" target="_4">GSA Search Interface</a>
            </li>
<li>
                <a href="http://en.wikipedia.org/wiki/PageRank" target="_5">Wikipedia Article on PageRank</a>
            </li>
<li>
                <a href="http://www.arnoldit.com/lists/google-patents.asp" target="_6">List of Google Patents</a>
            </li>
<li>
                <a href="http://googleenterprise.blogspot.com/2007/07/dont-believe-everything-you-read.html" target="_7">Google Enterprise Blog</a>
            </li>
<li>
                <a href="http://code.google.com/p/parametric/" target="_8">Google Enterprise Labs, Parametric</a>
            </li>
<li>
                <a href="http://code.google.com/enterprise/oneboxgallery.html" target="_9">Google Hosted OneBox Gallery</a>
            </li>
</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/google-enterprise-search-appliance-overview/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Simplifying Endeca Deployments: The Deployment Template</title>
		<link>http://www.bluefishgroup.com/2008/simplifying-endeca-deployments/</link>
		<comments>http://www.bluefishgroup.com/2008/simplifying-endeca-deployments/#comments</comments>
		<pubDate>Tue, 08 Apr 2008 11:00:00 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Information Access]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/2008/simplifying-endeca-deployments/</guid>
		<description><![CDATA[Introduction Endeca pipelines can be deployed in any number of ways, though some ways are better than others. How you implement and deploy Endeca pipelines can impact the maintainability and sustainability of your solution, and a good, clean deployment process can reduce the risk of future complications early on. Thankfully, Endeca has recently introduced a [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Introduction</a><br />
    </h3>
<p>Endeca pipelines can be deployed in any number of ways, though some ways are better than others.  How you implement and deploy Endeca pipelines can impact the maintainability and sustainability of your solution, and a good, clean deployment process can reduce the risk of future complications early on.  Thankfully, Endeca has recently introduced a generic deployment template which is based on best practices and deployment process standards.</p>
<p>This article will highlight the benefits of using the deployment template, address some common pitfalls of non-standardized deployments and  explain the basic scripting mechanisms provided by the template.  It is assumed that the reader has a basic understanding of developing Endeca pipelines and is deploying pipelines using at least Endeca Information Access Platform 5.0.</p>
<h3>
        <a name="head2" class="section">A Deployment without a Template</a><br />
    </h3>
<p>An Endeca pipeline deployment consists of configuring pipeline components and scripts in the Endeca Application Controller (or Job Control Daemon) and ensuring the pipeline can be kicked off via a script so that it can run on a schedule.</p>
<p>Prior to the introduction of Endeca<well_formed_html>&#8216;</well_formed_html>s deployment template, this deployment process was considered something of a black art, left only to those with the right kind of <i>know how</i>.  Without the template all the decisions of the deployment process are left to the developer, resulting in a deployment that is hard to understand for anyone not directly involved with it.  This easily leads to various problems down the road.</p>
<p>Because there was no mandatory way to configure an Endeca pipeline or its supporting scripts, a developer chose his own preferred method.  This made it difficult for another developer to understand the configuration.  If the pipeline was using auxiliary scripts, the developer may not have been using the provided scripting utility, this made it harder to coordinate scripts with the Endeca Application Controller and share scripts among other projects.  Additionally, logging and index archival did not typically exist, often resulting in a loss of essential log files and indices.</p>
<p>With the advent of the deployment template, all the guess work is taken out of deploying an Endeca pipeline.</p>
<h3>
        <a name="head3" class="section">Benefits of the Deployment Template</a><br />
    </h3>
<p>
	The release of Endeca&#8217;s generic deployment template enables developers to standardize the deployment process.  The deployment template is a set of scripts and configuration which takes care of a project&#8217;s deployment requirements.  The details of deployment requirements will be explained in depth later in the article.<br />
	The template provides many features to ease the deployment process.  Some of the features provided are:
	</p>
<ul>
<li>A centralized configuration for pipeline components and the Endeca Application Controller</li>
<li>A scripting platform which supports Java and is powered using BeanShell</li>
<li>Example scripts for performing baseline updates and partial crawls</li>
<li>Out of the box scripts for logging and archiving</li>
<li>Standardized directory structure and naming conventions</li>
</ul>
<p>
	These features are what make the deployment process easy, repeatable and supportable.  Anyone with experience using the template will easily understand any pipeline, its configuration, and its supporting scripts.
	</p>
<h3>
        <a name="head4" class="section">What is EAC?</a><br />
    </h3>
<p>Before we get too far, I want to provide a quick overview of what EAC, or the Endeca Application Controller, is and what it does.  The Endeca Application Controller, introduced in Endeca IAP 5.0, is a web service which manages the pipeline configuration, environment configuration and scripts.  EAC is also used to execute pipeline components and scripts it has been configured to run.
	</p>
<p>The user interface for EAC is a web application called Web Studio which can be used to view or update configuration information and execute scripts and components.  Since EAC runs as a web service, developers are not bound to using Web Studio to interact with it.  The deployment template configures EAC during initialization and updates, and developers are also free to interact with it.
	</p>
<h3>
        <a name="head5" class="section">Deployment Template Basics</a><br />
    </h3>
<p>
	The deployment template may be downloaded from Endeca&#8217;s support site.  The latest version at the time of this article is 2.1.
	</p>
<h4>Installing the Template</h4>
<p>In addition to its supporting install files the deployment template unzips to provide two scripts in the bin directory: deploy.bat or deploy.sh, to support both Windows and Unix/Linux environments.  Running the deploy script will prompt the user to verify the installed version of Endeca, along with a few questions: project name, installation location, and EAC port (the default EAC port is 8888).  This will configure the template to the user&#8217;s Endeca environment and install the template in the provided path.</p>
<h4>What&#8217;s in the Box</h4>
<p>There are a few files that are very relevant to using the template successfully.  This list is a breakdown of the most important paths and scripts provided:</p>
<p class="note">
        <b>Note: </b>In this article, it is assumed the template was installed under Windows, therefore all scripts have the .bat extension.  Had the template been installed in a *nix environment, everything would be the same except the scripts would have a .sh extension, built for running under those environments.  All behavior and functionality should remain the same.
	</p>
<p>    <well_formed_html></p>
<ul>
<li>config/pipeline/
<ul>
<li>This directory contains all of the pipeline files.  The generic template, as it is installed by the installer, comes pre-configured with Endeca&#8217;s wine pipeline.  This is provided so the template works &#8216;out of the box&#8217;. The wine pipeline will need to be removed to drop in a new pipeline.  Later in this section, I will explain how to remove the wine pipeline and provide a new one.
		</li>
</ul>
</li>
<li>config/script/AppConfig.xml
<ul>
<li>This is the heart of the template&#8217;s configuration.  When the initialization script is run, this file drives it.  The environment configuration, EAC configuration and scripts go in here.
		</li>
</ul>
</li>
<li>config/script/logging.properties
<ul>
<li>Contains the log4j configuration.</li>
</ul>
</li>
<li>config/script/set_environment.bat
<ul>
<li>This is used to set environment variables and is called when running any of the scripts provided in /control.</li>
</ul>
</li>
<li>control/initialize_services.bat
<ul>
<li>This file configures EAC according to AppConfig.xml.  EAC setup includes configuring Forge, Dgidx, MDEX engine, base scripts, daily, weekly and monthly report generation as well as any custom scripts or components provided in the AppConfig.</li>
</ul>
</li>
<li>control/baseline_update.bat
<ul>
<li>One of the default scripts provided in the AppConfig is BaselineUpdate.  This file sends the command to EAC to kick off the BaselineUpdate script.</li>
</ul>
</li>
<li>control/runcommand.bat
<ul>
<li>This can be used to run any command on EAC, for example &#8216;RunCommand BaselineUpdate&#8217; would run the BaselineUpdate script.</li>
</ul>
</li>
<li>control/set_baseline_data_ready_flag.bat
<ul>
<li>This file along with the set_partial_data_ready_flag is not a vital component of all pipelines.  Though the wine pipeline provided with the deployment template utilizes these mechanisms, other pipelines may not need to copy their baseline data and &#8216;ready&#8217; it, instead it may be on a database or website, and therefore this would not be used.  The implications of this will be described in further detail when I explain how to remove the wine pipeline and drop in a new pipeline.</li>
</ul>
</li>
<li>control/update_web_studio_config.bat
<ul>
<li>When initialize_services runs, it sets up the project in EAC for the first time.  If there is a need to update the configuration at a later time (perhaps due to changes in the AppConfig), this script can perform that task.  Alternatively, initialize_services may be used, but be warned &#8211; doing this will delete the existing project first.</li>
</ul>
</li>
</ul>
<p>    </well_formed_html></p>
<h3>
        <a name="head6" class="section">Installing a Pipeline</a><br />
    </h3>
<h4>Verify AppConfig</h4>
<p>Most of the default configurations and scripts provided by the deployment template in the AppConfig are good but there are a few things that might be worth double checking.</p>
<ul>
<li>In the global variables section, verify that the eacHost, eacPort and working directory are as specified during the template installation.</li>
<li>Under the server/hosts section, verify that the hostname attributes are specified as well.</li>
</ul>
<h4>How to Install the Pipeline</h4>
<p>Installing the pipeline involves removing the wine pipeline and its specific configuration, and replacing it with the new pipeline.  To accomplish this: </p>
<p>    <well_formed_html></p>
<ol>
<li>Delete all the files under /config/pipeline and copy the desired pipeline in its place.
<ul>
<li>The project name should be the same name prefixing the pipeline files. Make sure the new pipeline files have this name.</li>
<li>There are two options to fixing the names if they do not match:
<ul>
<li>Use Developer Studio to rename the pipeline.  To accomplish this, open the pipeline in Developer Studio and use the &#8216;Save As&#8230;&#8217; functionality to give it a new name. </li>
<li>Alternatively, the template can just be deployed with the name of the pipeline.</li>
</ul>
</li>
</ul>
</li>
<li>Delete the /test_data directory, as that data will no longer be needed.
<ul>
<li>The wine pipeline uses data provided in a data directory, but many pipelines do not depend on their data source being on the local disk.  So to create a generic template, it is important to modify the deployment template not to rely on such data sources.  The data that the wine pipeline uses ships with the deployment template under /test_data.  When running the provided BaselineUpdate script, this test data is copied into a holding directory, then a flag is set to signal that the data is ready.  Only then will the pipeline begin to process it.</li>
</ul>
</li>
<li>In the AppConfig, find the BaselineUpdate script.  Remove this if statement and its corresponding braces:  if (Forge.isDataReady())
<ul>
<li>The Forge.isDataReady flag is set by &#8216;load_baseline_test_data&#8217;.  This batch file copies the test data from its source directory (/test_data) into the projects &#8216;incoming&#8217; directory.  None of this is pertinent to a pipeline whose data is not immediately available locally.</li>
</ul>
</li>
<li>At this point, AppConfig is ready and the pipeline is in place. It is time to configure the project in EAC.  Configure EAC by running /control/initialize_services.bat
<ul>
<li>This will setup all the components and scripts in EAC.  Once this is done, the project will be accessible in Web Studio.  Logging in to Web Studio and clicking on &#8216;EAC Administration&#8217; will display the configuration as it is described in AppConfig.</li>
</ul>
</li>
<li>Finally, run the baseline script, /control/baseline_update.bat
<ul>
<li>This will run the Forge and Dgidx, and then start the index on the designated MDEX engine or Dgraph (the AppConfig refers to it as a Dgraph but in EAC it is referred to as the MDEX engine component.) </li>
</ul>
</li>
</ol>
<p>    </well_formed_html></p>
<p>Once the engine is running, the index may be viewed with the provided reference application.</p>
<h3>
        <a name="head7" class="section">Basics of EAC Scripting</a><br />
    </h3>
<p>EAC scripts are scripts that are written in Java (supported by the BeanShell framework) and live in the AppConfig xml file.  When the deployment template initializes or updates EAC with the AppConfig the provided scripts will be included as well.  Once a script is in EAC it can be kicked off from Web Studio or by sending a command from the command prompt.  There are a few scripts that are provided &#8216;out of the box&#8217;, and are a great starting point for writing scripts to meet your specific needs.<br />
	EAC scripts can be used for virtually any purpose imaginable.  The baseline script, for instance, will archive logs and the index, kick off a full crawl and then restart the engine.  Developers can write scripts that are necessary for their project as well.
	</p>
<p>
	Consider a project that has a pipeline component which depends on data that is retrieved from an LDAP server.  The developer can write an EAC script that will retrieve the data from LDAP and store it locally.  After the data is retrieved the script can kick off the crawl which processes the LDAP data.  Another scenario I&#8217;ve personally encountered is when an indexing process is dependent on the completion of several concurrent processes.  EAC can solve this using its provided lock manager, one of the many features of the EAC scripting framework, to synchronize the processes.  The concurrent processes can all obtain locks using the lock manager, and the index will wait for all the obtained locks to be released before executing.
	</p>
<p>The implementation details of EAC scripts are beyond the scope of this article, but the scripts that are provided out of the box are a great place to start.  EAC scripting is the optimal solution for supporting pipelines; its flexibility allows even the most complex problems to be solved.  Check back later for an article on EAC scripting.
	</p>
<h3>
        <a name="head8" class="section">Conclusion</a><br />
    </h3>
<p>The deployment template makes it easy to quickly deploy Endeca pipelines and provide excellent configuration management for the pipeline without additional development time.  Developers need not worry about a new index wiping out an old one or of log files over-writing each other as long as the deployment template is being leveraged, and configuring archaic control systems is no longer a concern either.  The deployment template will quickly become an essential part of any Endeca toolkit after just one use.</p>
<h4>References</h4>
<p>    <well_formed_html></p>
<ul>
<li>Learn more about BeanShell at <a href="http://www.beanshell.org">http://www.beanshell.org</a>.</li>
<li>Get the deployment template at <a href="http://support.endeca.com">http://support.endeca.com</a>.  Speak with your Endeca rep for access.</li>
</ul>
<p>
Mail questions or comments to:<br />
Apaar Trivedi (<a href="mailto:atrivedi@bluefishgroup.com">atrivedi@bluefishgroup.com</a>)
</p>
<p>    </well_formed_html>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/simplifying-endeca-deployments/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Custom Java Lifecycle Modules</title>
		<link>http://www.bluefishgroup.com/2008/custom-java-lifecycle-modules/</link>
		<comments>http://www.bluefishgroup.com/2008/custom-java-lifecycle-modules/#comments</comments>
		<pubDate>Tue, 08 Apr 2008 11:00:00 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Custom ECM Solutions]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/2008/custom-java-lifecycle-modules/</guid>
		<description><![CDATA[Overview Documentum lifecycles are used to implement business policies around the lifecycle of an object in the repository. For example, a news article might be authored in &#8220;Draft&#8221; state, then promoted to a &#8220;QC Review&#8221; state, and if accepted by an editor, promoted to &#8220;Final&#8221; or &#8220;Published&#8221; state. Each state in the lifecycle can be [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Overview</a><br />
    </h3>
<p>
	  Documentum lifecycles are used to implement business policies around the lifecycle<br />
	   of an object in the repository.  For example, a news article might be authored in<br />
	    &#8220;Draft&#8221; state, then promoted to a &#8220;QC Review&#8221; state, and if accepted by an editor,<br />
	     promoted to &#8220;Final&#8221; or &#8220;Published&#8221; state.  Each state in the lifecycle can be<br />
	      configured to perform certain actions as documents enter or leave it.</p>
<p>Some lifecycle actions, such as adding or removing version labels or assigning a new ACL,<br />
	 can be achieved through configuration of the out-of-the-box lifecycle functionality.<br />
	   However, more specialized actions require custom-coded lifecycle modules, which are<br />
	    the subject of this article.</p>
<p>This article assumes that the reader knows the basics of lifecycle creation and configuration.<br />
	  If you are unfamiliar with these concepts, please see the Documentum Content Server Fundamentals<br />
	   Guide (Chapter 10) or this excellent article from the dm_developer website:
	</p>
<p>    <a target="_blank" href="http://www.bluefishgroup.com/library/2002/creating-a-simple-lifecycle/">Creating a Simple Lifecycle</a></p>
<p>Document lifecycles (dm_policy objects) are typically constructed and administered via the Documentum<br />
	  Application Builder (DAB) interface.  This article focuses on lifecycle configuration performed in<br />
	   the DAB client.  You could also perform most of these tasks using DQL, the API, or DFC.  Custom<br />
	    Java code for lifecycles can be written in the editor/IDE of your choice.
	</p>
<h4>The Lifecycle Implementation Type</h4>
<p>Documentum lifecycles have an implementation type attribute which defaults to &#8220;Docbasic&#8221;.<br />
	  This value sets the code language for modules that can be called from the lifecycle&#8217;s state<br />
	   transitions.  (A state transition is the promotion or demotion of an object to a different<br />
	    lifecycle state.)  Because a lifecycle can only have one implementation type, it can only<br />
	     execute one type of code.   When using custom code modules written in Java, set the<br />
	      lifecycle&#8217;s implementation attribute to &#8220;Java&#8221; as described below.
	</p>
<ol>
<li>Using Documentum Application Builder, open the docapp that contains the lifecycle<br />
		 you want to configure (or create a new DocApp and Lifecycle).</li>
<li>Double-click and edit the lifecycle in the DocApp.</li>
<li>Set the &#8220;Implementation&#8221; drop-down value to &#8220;Java&#8221; on the &#8220;General&#8221; tab of the<br />
		 lifecycle configuration form.</li>
</ol>
<div align="center">
        <img src="/article-assets/images/sm_ann_set_lc_type1.jpg" border="0" alt="Fig. 1: Implementation Type">
<p class="figure">
            <b><br />
              Figure 1:<br />
            </b> Setting the Lifecycle&#8217;s Implementation Type</p>
</p></div>
<h4>Types of Lifecycle Modules</h4>
<p>Lifecycles can call custom code modules during state transitions.<br />
	  Each lifecycle state transition provides three opportunities to call<br />
	   custom code:</p>
<div class="indent">
        <em>Pre-Entry Modules</em> &#8211; Pre-entry modules are called prior to the state transition<br />
	    and can therefore be used for such functions as validating custom entry criteria<br />
	     or manipulating the transitioning object prior to the transition.  Pre-entry<br />
	      modules can block a state transition if the object fails custom validation<br />
	       or if an exception is raised.</div>
<div class="indent">
        <em>Action Modules</em> &#8211; Action modules are called during the state transition only after<br />
	    all entry criteria and pre-entry modules have executed successfully.  Documentum ships with<br />
	     several pre-built lifecycle actions for common state transition tasks (so don&#8217;t write a<br />
	      custom action unless you have to!).  The following actions are provided out-of-the-box:</p>
<ul>
<li>Add Attribute</li>
<li>Add Label</li>
<li>Add Link</li>
<li>Change Storage</li>
<li>Move Object</li>
<li>Remove Attribute</li>
<li>Remove Label</li>
<li>Remove Link</li>
<li>Rendition</li>
<li>Set Attribute</li>
</ul></div>
<div class="indent">
        <em>Post-Entry Modules</em> &#8211; Post entry modules are called after the transitioning<br />
	     object has entered the lifecycle state.  This occurs after all pre-entry and action<br />
	      modules have executed.
	    </div>
<h3>
        <a name="head2" class="section">Permissions for Lifecycle Modules</a><br />
    </h3>
<p>When you create a code module for your custom lifecycle code in DAB, it is<br />
	 automatically assigned the &#8220;BOF_acl&#8221; ACL which has permissions of Owner(Delete)<br />
	  and World(Read + Execute Procedure).  These permissions allow the lifecycle to<br />
	   execute modules on behalf of any user (World) who initiates a state transition.<br />
	      However, if the custom code itself tries to perform activities for which the<br />
	       lifecycle user does not have sufficient permssion then the following error<br />
	        is raised in the WDK client:</p>
<div align="center">
        <img src="/article-assets/images/sm_lc_permissions_error1.jpg" border="0" alt="Fig. 2: Permissions Error">
<p class="figure">
            <b><br />
              Figure 2:<br />
            </b> Error raised by lifecycle code executing with insufficient permission</p>
</p></div>
<p>If your custom lifecycle code needs to perform actions for which the individual lifecycle<br />
	  user does not have permission, then you can configure lifecycle actions to operate on<br />
	   behalf of a designated superuser (or any other user), rather than the lifecycle user.<br />
	      This configuration is stored in the &#8220;a_bpaction_run_as&#8221; attribute of the docbase<br />
	       configuration object, &#8220;dm_docbase_config&#8221;.  These are the valid values for the<br />
	        Docbase-level a_bpaction_run_as attribute:</p>
<ul>
<li>
            <em>session_user</em> (default) &#8211; Causes the lifecycle code to execute on behalf of<br />
	  	 the current session user, the user who initiated the state transition.</li>
<li>
            <em>superuser</em> &#8211; Causes lifecycle code to execute on behalf of a superuser,<br />
	  	 the docbase owner</li>
<li>
            <em>lifecycle_owner</em> &#8211; Causes lifecycle code to execute on behalf of the lifecycle owner,<br />
	  	 the owner_name of the lifecycle&#8217;s dm_policy object.</li>
<li>
            <em>&lt;user name&gt;</em> &#8211; Causes lifecycle code to execute on behalf of any designated user.<br />
	  	  Populate with the docbase user&#8217;s user_name.</li>
</ul>
<p>You can configure lifecycle actions to run on behalf of the desired user by executing a DQL<br />
	   command similar the one shown below:</p>
<div class="indent">update dm_docbase_config OBJECT set a_bpaction_run_as = &#8216;superuser&#8217;;</div>
<p>
        <em>Important Note:</em>  Configuring lifecycle actions to operate on behalf of another user can have the<br />
	  unintended side-effect of setting the document&#8217;s &#8216;Modified By&#8217; attribute (r_modifier) to the name<br />
	   of the designated user (a_bpaction_run_as), rather than the user who initiated the lifecycle<br />
	    state transition.</p>
<h3>
        <a name="head3" class="section">Writing Custom Lifecycle Code</a><br />
    </h3>
<p>In order for custom code to be callable from lifecycle states, it must implement the correct<br />
	 interface(s).   A single Java class can implement multiple interfaces and thus handle multiple<br />
	  events in the state transition.  A single lifecycle state transition has three events that<br />
	   can call out to your custom code: pre-entry, action, and post-entry.   The method signatures<br />
	    for each event are different, but their parameters are all the same:</p>
<ul>
<li>IDfSysObject &#8211; This is the repository object, usually a document, which is being<br />
		 transitioned in the lifecycle.</li>
<li>userName &#8211; This is either the user who initiated the lifecycle state transition<br />
		 or another pre-designated user that the lifecycle is configured to operate on<br />
		  behalf of (See Permissions for Lifecycles in this article).</li>
<li>targetState &#8211; This is the descriptive name of the lifecycle state being<br />
		 entered (not the current state index).  For example, &#8220;Draft&#8221;.</li>
</ul>
<p>The method signatures for the lifecycle state-transition events are described below.</p>
<h3>Pre-Entry</h3>
<p>A pre-entry lifecycle module must implement the IDfLifecycleUserEntryCriteria interface.<br />
	  This interface has a single public method, userEntryCriteria, which returns a Boolean value.<br />
	     A return value of True allows the object to enter the lifecycle state.  A return value<br />
	      of False or an exception will prevent the object from entering the target lifecycle state.</p>
<p>
        <em>Interface:</em>IDfLifecycleUserEntryCriteria</p>
<p>
        <em>Method Signature:</em>
    </p>
<pre>
        <code>
public boolean userEntryCriteria (   IDfSysObject obj,
 	                             String userName,
                                     String targetState) throws DfException {
       return true;    
}
</code>
    </pre>
<h3>Action</h3>
<p>A lifecycle action module must implement the IDfLifecycleUserAction interface.  This interface<br />
	 has a single public void method, userAction, in which you can perform custom actions on the object<br />
	  that is entering the lifecycle state.  Errors raised in custom lifecycle action code will not<br />
	   prevent an object from entering the lifecycle state.</p>
<p>
        <em>Interface:</em>IDfLifecycleUserAction</p>
<p>
        <em>Method Signature:</em>
    </p>
<pre>
        <code>
public boolean userAction (  IDfSysObject obj,
 	                     String userName,
                             String targetState) throws DfException {  
}
</code>
    </pre>
<h3>Post-Entry</h3>
<p>A post-entry lifecycle module must implement the IDfLifecycleUserPostProcessing interface.<br />
	  This interface has a single public void method, userPostProcessing, in which you can perform<br />
	   custom actions on the object after it has entered the lifecycle state.  Errors raised in<br />
	    custom lifecycle post-entry code will not prevent an object from entering the lifecycle state.</p>
<p>
        <em>Interface:</em>IDfLifecycleUserPostProcessing</p>
<p>
        <em>Method Signature:</em>
    </p>
<pre>
        <code>
public boolean userPostProcessing (  IDfSysObject obj,
 	                             String userName,
                                     String targetState) throws DfException {  
}
</code>
    </pre>
<h3>
        <a name="head4" class="section">Getting a User Session</a><br />
    </h3>
<p>Code in lifecycle modules can retrieve a user session from the SysObject parameter.</p>
<div class="indent">IDfSession user Session = obj.getSession();</div>
<p>If the docbase is configured to run lifecycle methods as a special user/superuser,<br />
	 then a session will be returned for that specific user.  Otherwise, the command will<br />
	  return a session for the user who initiated the lifecycle state transition (this is<br />
	   the default behavior).</p>
<h3>
        <a name="head5" class="section">Creating a Lifecycle Code Module</a><br />
    </h3>
<p>After you have created a Java class that implements one or more of the lifecycle state<br />
	 transition interfaces, add it to its own jar file and copy the jar file to a location<br />
	  where it can be accessed via DAB.  Note that lifecycle modules do NOT require you to<br />
	   package separate interface and implementation classes in your jar file (as is the<br />
	    case for TBO and SBO modules).  Only the implementation class is necessary for<br />
	     lifecycle modules.</p>
<p>Before your custom code can be called from a lifecycle it must first be added to the Docapp<br />
	 (and docbase) as a custom code module.  This can be done via the Insert-&gt;Module feature<br />
	  of Documentum Application Builder (DAB) client.</p>
<div align="center">
        <img src="/article-assets/images/sm_ann_create_lc_module1.jpg" border="0" alt="Fig. 3: Create Module">
<p class="figure">
            <b><br />
              Figure 3:<br />
            </b> Creating a new code module in DAB</p>
</p></div>
<p>
        <em>Important Note:</em> You will have to manually type the word &#8220;Lifecycle&#8221; into the module<br />
	 type drop-down box because it will not appear as an option.</p>
<p>When you check-in the new module in the Docapp, a new folder of type dmc_module is<br />
	  created in the Lifecycle Modules area of the docbase containing the module&#8217;s jar file(s)<br />
	   as dmc_jar objects.</p>
<div align="center">
        <img src="/article-assets/images/ann_module_in_docbase.jpg" border="0" alt="Fig. 4: Code Module in Docbase">
<p class="figure">
            <b><br />
              Figure 4:<br />
            </b> A custom lifecycle module stored in the docbase</p>
</p></div>
<h3>
        <a name="head6" class="section">Configuring a Lifecycle to Use Custom Modules</a><br />
    </h3>
<p>Now that the custom code has been packaged and added to the docapp as a lifecycle module,<br />
	 the lifecycle states can be configured to call the module.</p>
<ol>
<li>Edit the state of your lifecycle from which you want to call a custom module.</li>
<li>Select the tab corresponding to the transition event that should call your custom<br />
		 code (entry Criteria, Actions, or PostChange)</li>
<li>Use the Module Name control to browse to and select your custom jar file.</li>
<div align="center">
            <img src="/article-assets/images/set_pre.jpg" border="0" alt="Fig. 5: Pre-entry Module">
<p class="figure">
                <b><br />
              Figure 5:<br />
            </b> Configuring the lifecycle state to call a custom pre-entry module in DAB</p>
</p></div>
<li>Don&#8217;t forget to validate and re-install the lifecycle after modifications by<br />
		 pressing the &#8220;Validate&#8221; and &#8220;Install&#8221; button on the &#8220;General&#8221; tab.  Note that this<br />
		  button changes its label each time you press it.</li>
</ol>
<p>
        <em>Note:</em> If your module does not include a class that implements the corresponding interface,<br />
	 for the transition event then your module will not appear as a choice for the state transition in DAB.</p>
<h3>
        <a name="head7" class="section">Handling Exceptions</a><br />
    </h3>
<p>All of the lifecycle state transition interfaces throw DfException.   If custom code within your<br />
	 module throws other types of errors, it&#8217;s a good idea to roll them up to a DfException and set the<br />
	  error message string to something meaningful.  The custom error message will be displayed to the<br />
	   transition initiator in WDK clients.  The code snippet below shows how to create a DfException,<br />
	    set its error message string, and throw it.</p>
<pre>
        <code>
             DfException ex = new DfException();
             ex.setMessage("Hello this is a problem");
             throw ex;
	</code>
    </pre>
<p>
        <em>Best Practice:</em> In pre-entry methods, when an object fails validation, it&#8217;s a good idea to<br />
	 raise a DfException and set the error message string to something specific and informative,<br />
	  rather than to simply return False.  If you only return a value of False, then a generic<br />
	   error message is returned to the user in the WDK client that gives no indication as to<br />
	    what specifically caused the validation issue.</p>
<div align="center">
        <img src="/article-assets/images/ann_exception_message.jpg" border="0" alt="Fig. 6: Exception Message">
<p class="figure">
            <b><br />
              Figure 6:<br />
            </b> A pre-entry validation error showing a custom error message</p>
</p></div>
<h3>
        <a name="head8" class="section">Wrap-up</a><br />
    </h3>
<p>Custom lifecycle modules are a very powerful tool for Documentum developers in that<br />
	 they allow the addition of custom business logic to lifecycle states.   Documentum&#8217;s<br />
	  out-of-the-box lifecycle functionality is extensive and often covers a solution&#8217;s<br />
	   business requirements solely through configuration.  However, business requirements<br />
	    sometimes fall outside of the capabilities of the standard Documentum lifecycle<br />
	     feature set.  This is where custom lifecycle modules can really save the day!</p>
<p>If you have any questions or comments about this article, please feel free to contact<br />
	 the author at gtarrant@bluefishgroup.com.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.bluefishgroup.com/2008/custom-java-lifecycle-modules/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>DFC Search In Depth</title>
		<link>http://www.bluefishgroup.com/2008/dfc-search-in-depth/</link>
		<comments>http://www.bluefishgroup.com/2008/dfc-search-in-depth/#comments</comments>
		<pubDate>Tue, 08 Apr 2008 11:00:00 +0000</pubDate>
		<dc:creator>Blue Fish Development Group</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Custom ECM Solutions]]></category>

		<guid isPermaLink="false">http://www.bluefishgroup.com/library/2008/dfc-search-in-depth/</guid>
		<description><![CDATA[Introduction This article explores Documentum search features with a heavy focus on the Java DFC APIs related to search. Documentum product manuals are invaluable resources in coming to understand these concepts, but in many cases they are missing important details&#8211;details that you would otherwise have to learn via prototyping and trial and error. In this [...]]]></description>
				<content:encoded><![CDATA[<div class="article_text">
<h3>
        <a name="head1" class="section">Introduction</a><br />
    </h3>
<p>
This article explores Documentum search features with a heavy focus on the Java DFC APIs related to search.<br />
Documentum product manuals are invaluable resources in coming to understand these concepts,<br />
but in many cases they are missing important details&#8211;details that you would otherwise have to<br />
learn via prototyping and trial and error. In this article I&#8217;ll attempt to cover these missing<br />
details while providing a focused overview of DFC search and query features.</p>
<h3>
        <a name="head1" class="section">The Simple Query API</a><br />
    </h3>
<p>DFC&#8217;s simple query API allows you to execute queries expressed as DQL strings. Here&#8217;s an example:</p>
<pre>
        <code>
    public IDfCollection getLargeDocuments(IDfSession session) 
    throws DfException
    {
        IDfQuery query = new DfClientX().getQuery();
        query.setDQL(
           "SELECT * FROM dm_document " +
                      " WHERE r_full_content_size &gt; 1000000");
        return query.execute(session, IDfQuery.DF_READ_QUERY);
    }
</code>
    </pre>
<p>Here, we create an <code>IDfQuery</code> instance using the factory method <code>IDfClientX.getQuery()</code>. Then we populate the query with a valid DQL string and call the query&#8217;s <code>execute()</code> method with an <code>IDfSession</code> instance.</p>
<p>DFC documentation refers to this as &#8220;the simple query API.&#8221; There are some significant limitations to this API:</p>
<ul>
<li>Only queries on a single repository are permitted. The target of the query is implicitly the default repository of the provided <code>IDfSession</code>.</li>
<li>Only Documentum repositories can be queried. You cannot query an external, federated (ECIS) source.</li>
<li>There is no support for programmatically building queries; only explicit DQL query strings are supported.</li>
<li>Executing a query is always a thread-blocking operation; that is, the thread issuing the API call blocks until the query results are returned.</li>
</ul>
<p>The search service API, included in Documentum 5.3 SP1 and later releases, resolves these limitations. The next section covers this extensive API in detail.</p>
<h3>
        <a name="head1" class="section">The Search Service API</a><br />
    </h3>
<p>The search service API is rooted at the <code>IDfSearchService</code> interface:</p>
<p><div align="center">
            <img src="/article-assets/images/IDfSearchService.jpg" border="0" alt="Fig. 1">
<p class="figure">
                <b><br />
              Figure 1:<br />
            </b> The IDfSearchService interface.</p>
</p></div>
</p>
<p>To obtain an instance of this class, use <code>IDfClient.newSearchService()</code>:</p>
<pre>
        <code>
IDfSearchService searchService = 
   new DfClientX().getLocalClient().newSearchService(mgr, repo);
</code>
    </pre>
<p>The first parameter of the <code>newSearchService()</code> factory method is an <code>IDfSessionManager</code> that knows connection credentials for all of the repositories you wish to query. The second parameter is a <code>String</code> that specifies the default repository to use for metadata when querying external ECIS sources&#8211;you can use null for this parameter in the case that you are only searching Documentum repositories.
<p class="note">
            <b>Note: </b>ECIS is a Documentum technology that allows arbitrary (non-Documentum) content sources to be adapted and accessed via Documentum search.</p>
</p>
<h4>Building Queries</h4>
<p>Now that we have a search service instance, how do we create a query and then execute it? The way queries are built using the search service API is not through DQL&#8211;in fact, the API doesn&#8217;t accept DQL at all. Instead, the API requires you to express your query using a query builder (or <em>criteria</em>) API. With this API, you build your query programmatically using the <code>IDfQueryBuilder</code> and related interfaces in the DFC package <code>com.documentum.fc.client.search</code>. Here&#8217;s a simple example that demonstrates building a query using <code>IDfQueryBuilder</code>. The query finds all <code>dm_document</code>s whose <code>object_name</code> attribute contains the word &#8220;sphygmomanometer&#8221;:</p>
<pre>
        <code>
 IDfQueryManager queryManager = searchService.newQueryMgr();
 IDfQueryBuilder query = queryMgr.newQueryBuilder("dm_document");
 IDfExpressionSet root = builder.getRootExpressionSet();
 root.addSimpleAttrExpression(
     "object_name",
     IDfValue.DF_STRING,
     IDfSimpleAttrExpression.SEARCH_OP_CONTAINS,
     true /* isCaseSensitive */,
     false /* isRepeated */,
     "sphygmomanometer");
</code>
    </pre>
<p>There are several methods on the <code>IDfQueryBuilder</code> interface that allow you to specify the details of your query, but in this example we keep things simple and express the query as a single attribute constraint. To understand this API, it helps to see the DQL-equivalent of the built query:</p>
<pre>
        <code>
SELECT * FROM dm_document 
    WHERE object_name LIKE '%sphygmomanometer%'
</code>
    </pre>
<p>We should point out that the search service actually generates DQL under the covers for search sources that are Documentum repositories. You can actually see the generated DQL for searches like these by enabling the <code>com.documentum.fc.client.search.impl.generation</code> log in the DFC log4j configuration.</p>
<p>The above query selects all attributes in the query. You can scope the result attributes by specifying them explicitly:</p>
<pre>
        <code>
  query.addResultAttribute("object_name");
</code>
    </pre>
<p>This example restricts the query&#8217;s selected attributes to <code>object_name</code>. In this case, the query builder API will automatically add <code>r_object_id</code> to the selected attributes list. If the built query contains a full-text expression, then <code>score</code> will also be added to the selected attribute list.</p>
<p>Attribute constraints are added to an <code>IDfQueryBuilder</code> query through its expression set tree rooted at <code>IDfQueryBuilder.getRootExpressionSet()</code> which returns an <code>IDfExpressionSet</code> instance. With this interface you can express arbitrary, nested logical expressions. We&#8217;ll look at a more complicated example, but first let&#8217;s introduce a little &#8220;adaptor method&#8221; to simplify our code&#8211;the <code>addSimpleAttrExpression()</code> is just too lengthy:</p>
<pre>
        <code>
    /**
     * Add a case-insensitive 'contains' constraint to the 
     * provided {@link IDfExpressionSet}. Assume the provided 
     * attribute name identifies a non-repeating String 
     * attribute.
     */
    void addContains(IDfExpressionSet expressionSet, 
                     String attributeName, 
                     String value) 
    {
        expressionSet.addSimpleAttrExpression(attributeName,
            IDfValue.DF_STRING, 
            IDfSimpleAttrExpression.SEARCH_OP_CONTAINS, 
            false /* isCaseSensitive */, 
            false /* isRepeated */, 
            value);
    }
</code>
    </pre>
<p>Now we can add simple attribute expressions in a much more concise form:</p>
<pre>
        <code>
    public IDfQueryBuilder buildQuery(IDfQueryManager queryMgr) 
    throws DfException 
    {
        // This no-arg factory method defaults to search type
        // "dm_sysobject"
        IDfQueryBuilder query = queryMgr.newQueryBuilder();
        IDfExpressionSet root = query.getRootExpressionSet();
        addContains(root, "object_name", "Some File");
        addContains(root, "owner_name", "Zarnk");
        IDfExpressionSet sub = root.addExpressionSet();
        sub.setLogicalOperator(IDfExpressionSet.LOGICAL_OP_OR);
        addContains(sub, "subject", "mnemonist");
        addContains(sub, "title", "mnemonist");
        return query;
    }
</code>
    </pre>
<p>Note the use of the <code>setLogicalOperator()</code> method. Each expression set has an associated logical operator (one of <code>AND</code> or <code>OR</code>) . The default operator is <code>AND</code>, which is why we don&#8217;t have to set the logical operator for the root set. Also note that the <code>OR</code> expression set is added as a member of the <code>AND</code> expression set to form a nested expression. In DQL, the corresponding criteria is: </p>
<pre>
        <code>
 ... FROM dm_sysobject WHERE 
      (object_name LIKE '%Some File%' 
          AND owner_name LIKE '%Zarnk%'  
              AND (subject LIKE '%mnemonist%' 
                       OR title LIKE '%mnemonist%'))
</code>
    </pre>
<h4>IDfExpressionSet in Detail</h4>
<p>
        <code>IDfExpressionSet</code> is an important part of the query builder API. Here is the full interface:</p>
<p><div align="center">
            <img src="/article-assets/images/IDfExpressionSet.jpg" border="0" alt="Fig. 2">
<p class="figure">
                <b><br />
              Figure 2:<br />
            </b> The IDfExpressionSet interface.</p>
</p></div>
</p>
<p>The <code>addFullTextExpression()</code> method has very interesting undocumented behavior, so let&#8217;s explore it before we move on. It&#8217;s easy to guess the semantics of the following query:</p>
<pre>
        <code>
   IDfQueryBuilder query = queryManager.newQueryBuilder();
   IDfExpressionSet root = query.getRootExpressionSet();
   root.addFullTextExpression("Hello");
</code>
    </pre>
<p>The DQL equivalent of this query is as you would expect:</p>
<pre>
        <code>
  ... FROM dm_sysobject SEARCH DOCUMENT CONTAINS 'Hello'
</code>
    </pre>
<p>But what about the following query?</p>
<pre>
        <code>
 IDfQueryBuilder query = queryMgr.newQueryBuilder("dm_document");
 IDfExpressionSet root = query.getRootExpressionSet();
 root.addFullTextExpression("Hello");
 root.addFullTextExpression("Goodbye");
 IDfExpressionSet sub = root.addExpressionSet();
 sub.setLogicalOperator(IDfExpressionSet.LOGICAL_OP_OR);
 sub.addFullTextExpression("Whaddup");
 addContains(sub, "object_name", "horsefeathers");
</code>
    </pre>
<p>This appears to be a valid search for all documents that contain &#8220;Hello&#8221; and &#8220;Goodbye&#8221; and either contain &#8220;Whaddup&#8221; or have an <code>object_name</code> that matches &#8220;horsefeathers&#8221;. This query cannot be expressed in DQL; in DQL syntax, the <code>SEARCH DOCUMENT CONTAINS</code> clause is separate from the <code>WHERE</code> clause so there is no way to mix full-text search contraints and metadata constraints in a logical expression. It turns out that this query is not supported by the search service API, either. At runtime, the above query will produce in an <code>INVALID_FULLTEXT_EXPRESSION</code> error when executed.</p>
<p>(There is a caveat to this, however. If full-text indexing is disabled in dfc.properties via the <code>dfc.search.fulltext.enabled</code> property, each full-text expression in the above query is automatically converted into a metadata constraint and the query will be succesfully built and executed.)</p>
<p>We&#8217;re still not done with the <code>addFullTextExpression()</code> method. Take a look at the following query and try to guess what DQL is generated for it:</p>
<pre>
        <code>
    IDfQueryBuilder query = queryManager.newQueryBuilder();
    IDfExpressionSet root = query.getRootExpressionSet();
    root.addFullTextExpression("Bob or Sue");
</code>
    </pre>
<p>Here&#8217;s a hint. It&#8217;s one of the following:</p>
<pre>
        <code>
(a) ...FROM dm_sysobject SEARCH DOCUMENT CONTAINS ('Bob or Sue')
(b) ...FROM dm_sysobject SEARCH DOCUMENT CONTAINS ('Bob' or 'Sue')
</code>
    </pre>
<p>These are two very different queries that produce drastically different result sets, so the answer is important. Okay, let&#8217;s kill the suspense&#8211;it&#8217;s <em>(b)</em>. When the query is prepared for execution, the search service acknowledges the lexical forms of the operators <code>AND</code> and <code>OR</code> when parsing each full-text value and generates DQL with the criteria separated by each operator (also acknowledging parantheses.) In some sense, this is very convenient behavior&#8211;when offering a search box to a user in a UI, for example, we won&#8217;t have to do this parsing ourselves.</p>
<h4>Searching Multiple Repositories</h4>
<p>One significant feature of the search service API is its ability to execute a query across multiple repositories. The <code>addSelectedSource()</code> method on the <code>IDfQueryBuilder</code> interface specifies which sources the query should search. As expected, not adding any such selected sources to your query will result in empty results.</p>
<p>As an example, let&#8217;s suppose we wish to search two repositories &#8220;gargamel&#8221; and &#8220;punky&#8221;. Here&#8217;s how you would add these sources to your query:</p>
<pre>
        <code>
    IDfQueryBuilder query = ... 
    query.addSelectedSource("gargamel");
    query.addSelectedSource("punky");
</code>
    </pre>
<p>Recall that the search service we use to execute our search must be created with a session manager that knows the credentials required to access these repositories. Otherwise, the search service will generate errors during query execution.</p>
<p>You can also dynamically query for available sources using <code>IDfSearchService.getSourceMap()</code>. The following example adds all available sources (those visible to the doc broker(s) that are configured in <code>dfc.properties</code>) to a query:</p>
<pre>
        <code>
   IDfSearchSourceMap sourceMap = searchService.getSourceMap();
   IDfEnumeration sources =
      sourceMap.getAvailableSources(IDfSearchSource.SRC_TYPE_DOCBASE);
   while (sources.hasMoreElements()) {
      IDfSearchSource source = (IDfSearchSource) sources.nextElement();
      query.addSelectedSource(source.getName());
   }

</code>
    </pre>
<h4>Executing Queries</h4>
<p>Now that we know how to build a query, let&#8217;s demonstrate how to execute one:</p>
<pre>
        <code>
    IDfQueryProcessor processor = 
        service.newQueryProcessor(query, true /* noDuplicates */);
    processor.blockingSearch(0);
    IDfResultsSet results = processor.getResults();
</code>
    </pre>
<p>This example uses the search service to create an <code>IDfQueryProcessor</code> that can execute the search. Then, a blocking search is issued with a timeout of 0 to indicate that the calling thread should not timeout until the search is finished executing. We can also initiate a non-blocking search and monitor the processor for the results as they come in. If you&#8217;ve ever developed a WDK application, this is what the WDK search component does in order to dynamically display the status of a search to the user. We&#8217;ll touch on asynchronous search in the next section.</p>
<h4>Advanced Topics</h4>
<p>
        <strong>Asynchronous Search</strong>
    </p>
<p>Aysnchronous searches are invoked via the <code>IDfQueryProcessor.search()</code> method:</p>
<pre>
        <code>
    final IDfQueryProcessor processor = 
        service.newQueryProcessor(query, true /* removeDupes */);
    processor.addListener(new MyQueryListener());
    processor.search();
    IDfResultsSet results = processor.getResults();
</code>
    </pre>
<p>In this example, we create a listener (implementing <code>IDfQueryListener</code>) that will be notified of search events such as when the search is completed. Then we invoke the query processor&#8217;s asynchronous <code>search()</code> method. This method delegates the query processing to separate thread(s) that are responsible for sending the query to the various repositories and collecting and arregating the results. The processor listener we provided will be notified of various events during the results processing.</p>
<p>Because this is an asynchronous search, the thread that invokes the <code>search()</code> method cannot expect the results to be complete right away. The <code>results</code> object in the code above will be populated as the search results are processed. There are couple of ways to determine the status of the search as it is being processed&#8211;one is to use a listener object as demonstrated in the above example. Another approach is to use the <code>IDfQueryProcessor.getQueryStatus()</code> method to poll for the status. Note that polling query status in a non-blocking loop is a bad idea&#8211;this is the <a target="_blank" href="http://en.wikipedia.org/wiki/Busy_waiting">Busy Waiting</a> antipattern.</p>
<p>
        <strong>Results Processing</strong>
    </p>
<p>The previous discussions have demonstrated how to obtain query results when issuing queries through the Search Service API. These results are returned as <code>IDfResultsSet</code> instances. Here we show an example that processes an <code>IDfResultsSet</code> instance by displaying the <code>object_name</code> attribute value for each result entry:</p>
<pre>
        <code>
    private void showResultObjectNames(IDfResultsSet results) {
        for (int i = 0; i &lt; results.size(); ++i) {
            IDfResultEntry result = results.getResultAt(i);
            String objectName = result.getString("object_name");
            System.out.println(objectName);
        }
    }
</code>
    </pre>
<p>The <code>IDfResultEntry</code> interface is extensive; more details can be found in the DFC Javadocs.</p>
<p>
        <strong>Results Sorting</strong>
    </p>
<p>How can we sort results returned through the Search Service API? Use <code>IDfSearchService.newResultsManipulator()</code> to create an instance of <code>IDfResultsManipulator</code>, which you can then use to sort query results:</p>
<pre>
        <code>
    IDfResultsManipulator manipulator = 
        searchService.newResultsManipulator(query);
    IDfResultsSet sorted = 
        manipulator.sortBy(results, "object_name", true);
</code>
    </pre>
<p>If the results here are from an asynchronous search, then when the sort is issued only, the currently accumulated results are sorted and a new <code>IDfResultSet</code> instance is returned.</p>
<p>
        <strong>Metadata Manager</strong>
    </p>
<p>In some cases it is necessary at runtime to determine metadata about the types and attributes we are searching. Suppose you are building a query and wish to add a constraint on a given attribute. If the attribute isn&#8217;t explicitly known to you at development time (for example, it comes from a UI interaction or from user-supplied configuration), then you will need a way to determine certain characteristics of the attribute (e.g., Is it a repeating attribute? What is it&#8217;s datatype?) in order to add the constraint. <code>IDfSearchMetadataManager</code> can answer these questions. Using a metadata manager, we can create helpful, generic methods like this one:</p>
<pre>
        <code>
  /**
   * Add an equals constraint to the provided query's root
   * expression set using the provided attributeName and value.
   */
  public void addEqualsToRootExpression(IDfQueryBuilder query, 
                                        String attributeName, 
                                        String value) 
                                        throws DfException 
  {
      IDfSearchMetadataManager metadata = query.getMetadataMgr();
      IDfExpressionSet root = query.getRootExpressionSet();
      IDfSearchTypeAssistant type = 
          metadata.getTypeAssistant(query.getObjectType());
      root.addSimpleAttrExpression(attributeName,
          type.getAttrDataType(attributeName), 
          IDfSimpleAttrExpression.SEARCH_OP_EQUAL, 
          true /* isCaseSensitive */, 
          type.isAttributeRepeated(attributeName), 
          value);
  }
</code>
    </pre>
<p>There are a couple of things to point out here. Each query has its own metadata manager available via <code>IDfQueryBuilder.getMetadataMgr()</code>. Note also that the metadata manager uses the target repositories for the query to answer metadata information. What this means is that whenever you use <code>IDfQueryBuilder.addSelectedSource()</code>, you potentially change the state of the <code>IDfSearchMetadataManager</code> underlying the search.</p>
<p>Note that the metadata manager will only provide metadata for types that have the property <code>is_searchable</code> set to true.</p>
<p>
        <strong>Expression Set Manipulation</stro