<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:clearspace="http://www.jivesoftware.com/xmlns/clearspace/rss" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>Jivespace Community Blog</title>
    <link>http://www.jivesoftware.com/jivespace/blogs/jivespace</link>
    <description>Jivespace Developer Community Blog</description>
    <pubDate>Mon, 07 Jul 2008 16:43:25 GMT</pubDate>
    <generator>Clearspace 2.5.3 (http://jivesoftware.com/products/clearspace/)</generator>
    <dc:date>2008-07-07T16:43:25Z</dc:date>
    <item>
      <title>Customization Part 7: Using the Clearspace API</title>
      <link>http://www.jivesoftware.com/jivespace/blogs/jivespace/2008/07/16/customization-part-7-using-the-clearspace-api</link>
      <description>&lt;!-- [DocumentBodyStart:0f846e5e-081f-4f97-8e0b-a277f0d20817] --&gt;&lt;div class='jive-rendered-content'&gt;&lt;p&gt;This post is the seventh and final post in a series of blog posts about customizing for Clearspace 2.x. The previous posts covered:&lt;/p&gt;&lt;ol&gt;&lt;li level="1" type="ol"&gt;&lt;p&gt;&lt;a class="jive-link-external-small" href="http://www.jivesoftware.com/community/blogs/clearspace/2008/06/24/customizations-in-clearspace-2x-part-one/"&gt;Customizations in Clearspace 2.x&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ol"&gt;&lt;p&gt;&lt;a class="jive-link-external-small" href="http://www.jivesoftware.com/community/blogs/clearspace/2008/06/26/customization-part-2-upgrading-themes-and-ftl-files/"&gt;Upgrading Themes and FTL Files&lt;/a&gt;. &lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ol"&gt;&lt;p&gt;&lt;a class="jive-link-external-small" href="http://www.jivesoftware.com/community/blogs/clearspace/2008/06/30/customization-part-3-widgets"&gt;Widgets in Clearspace 2.x&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ol"&gt;&lt;p&gt;&lt;a class="jive-link-external-small" href="http://www.jivesoftware.com/community/blogs/clearspace/2008/07/03/customization-part-4-macros"&gt;Macros for Clearspace 2.0&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ol"&gt;&lt;p&gt;&lt;a class="jive-link-external-small" href="http://www.jivesoftware.com/community/blogs/clearspace/2008/07/07/customization-part-5-web-services"&gt;Web Services&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ol"&gt;&lt;p&gt;&lt;a class="jive-link-external-small" href="http://www.jivesoftware.com/community/blogs/clearspace/2008/07/11/customization-part-6-custom-authentication-and-user-data-providers"&gt;Custom Authentication and User Data Providers&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Some of the most important changes in version 2 of Clearspace required that the underlying API be changed. To get things working on version 2, you'll need to change not only references to these in your Java classes, but also references to them in your FreeMarker templates.&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;The following describes the most significant changes.&lt;/p&gt;&lt;ul&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;Inject Dependencies with Spring &lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;Work with Containers for Projects and Spaces/Communities &lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;Use Transaction Support When Updating Multiple Tables &lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;Use Manager Interfaces to Work with Managed Things &lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;Handle Content As XML &lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;Other API Changes &lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;span&gt;Inject Dependencies With Spring&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;For version 2, the Clearspace codebase was refactored to support &lt;a class="jive-link-external-small" href="http://en.wikipedia.org/wiki/Spring_Framework"&gt;Spring&lt;/a&gt;, a framework with modules for inversion of control, transaction management, authentication, and more. This has potentially the biggest impact on your code because components that extend Clearspace must use the same conventions in order to interact reliably with Clearspace. For example, as described below, dependency injection replaces version 1 conventions for using JiveContext and factory classes to get manager instances.&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;a class="jive-link-external-small" href="http://en.wikipedia.org/wiki/Dependency_Injection"&gt;Dependency injection&lt;/a&gt; is a way to obtain a dependency, such as an object on which your code relies, by having the instance "injected" at run time&amp;nbsp; -- that is, the instance is set with a JavaBeans-style accessor method. In Clearspace code, manager class instances are generally now injected rather than obtained via a context or factory class method.&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;A class that supports injection includes a class-level ++ variable for holding the instance it depends on and provides a set* accessor method through which Spring can inject the instance (in other words, your code provides a property of the interface's type). Your setter implementation assigns the injected instance to the variable, which your code can then use to access the instance. By specifying the &lt;em&gt;interface&lt;/em&gt; on which your code depends&amp;nbsp; -- rather than an implementation of the interface&amp;nbsp; -- you have a loosely-coupled dependency. This lets you avoid breakage that might occur if the implementation changes.&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;blockquote class="jive-quote" level="1"&gt;&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; You can ensure that the setter you provide actually has a configured type associated with it by &lt;a class="jive-link-external-small" href="http://static.springframework.org/spring/docs/2.5.x/reference/metadata.html#metadata-annotations-required"&gt;annotating the setter method with @org.springframework.beans.factory.annotation.Required&lt;/a&gt;. If the injected type is not known to Spring configuration, then the Spring container will throw an exception at run time.&lt;/p&gt;&lt;/blockquote&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;The following example illustrates the basics of dependency injection with Spring: declare private class-level variables for manager instances and declare setter methods through which Spring will inject the instances. Code for version 1 techniques has been commented out in favor of the Spring conventions.&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;!--[CodeBlockStart:2d9070ae-31f4-4afa-8534-c93bd3f42613]--&gt;&lt;pre class="jive-pre"&gt;&lt;code class="jive-code"&gt;// Variables to hold the manager instances.
private DocumentManager documentManager;
private FreemarkerManager freemarkerManager;


// Setters for injecting manager instances.
public void setDocumentManager(DocumentManager documentManager) {
&amp;nbsp;&amp;nbsp;&amp;nbsp; this.documentManager = documentManager;
}
public void setFreemarkerManager(FreemarkerManager freemarkerManager) {
&amp;nbsp;&amp;nbsp;&amp;nbsp; this.freemarkerManager = freemarkerManager;
}

private String getDocContent(String documentID)
{
&amp;nbsp;&amp;nbsp;&amp;nbsp; // ... Declare variables ... 
&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Don't use JiveContext (from JiveApplication) to get a DocumentManager 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // instance. The instance has been injected through the setter above.
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // DocumentManager documentManager = JiveApplication.getContext(AuthFactory
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;&amp;nbsp;&amp;nbsp; .getSystemAuthToken()).getDocumentManager();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Use the manager to get a document by its ID.
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; document = documentManager.getDocument(documentID);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Map properties = new HashMap();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ... Set FreeMarker properties from the document, then apply 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // a template with them ...
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result = applyFreemarkerTemplate(properties, FREEMARKER_HTML_FILE);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&amp;nbsp;&amp;nbsp;&amp;nbsp; // ... catch exceptions ...

&amp;nbsp;&amp;nbsp;&amp;nbsp; return result;
}

private String applyFreemarkerTemplate(Map properties,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; String templateName) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&amp;nbsp;&amp;nbsp;&amp;nbsp; // ... Declare variables ... 
&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Don't use getInstance to get the FreemarkerManager instance. It has 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // been injected.
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // FreemarkerManager freemarkerManager = FreemarkerManager.getInstance();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // ... Use the manager to set up FreeMarker configuration ...
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; config = freemarkerManager.getConfiguration(ServletActionContext.getServletContext());
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (properties != null) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Process the FreeMarker template and store the resulting HTML as a String
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result = applyFreemarkerTemplate(config, properties, templateName);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 
&amp;nbsp;&amp;nbsp;&amp;nbsp; // ... catch exceptions ...

&amp;nbsp;&amp;nbsp;&amp;nbsp; return result;
}&lt;/code&gt;&lt;/pre&gt;&lt;!--[CodeBlockEnd:2d9070ae-31f4-4afa-8534-c93bd3f42613]--&gt;&lt;p&gt;While you can optionally name the specific interface implementation you want to have injected, Spring in Clearspace supports a feature known as autowiring. In autowiring, you merely include the setter method (using JavaBeans naming conventions) with a single parameter of the interface's type. To optionally specify the implementation you want injected, you include a spring.xml file that associates the implementation class with your setter.&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Remove JiveContext uses that retrieve managers.&lt;/strong&gt; In version 1 the JiveContext interface was a popular convention to get instances of the various manager interfaces&amp;nbsp; -- CommunityManager, UserManager, DocumentManager, and so on. In version 2 this convention is, depending on the case, either unavailable or unreliable. For example, if you've written a plugin that has a static initializer that tries to bootstrap with call to JiveContext, Clearspace startup will likely fail.&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Instead, use dependency injection as described above. In fact, to stay out of trouble, the general rule in version 2 is "Don't use JiveContext."&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Remove getInstance calls that retrieve managers.&lt;/strong&gt; This includes FreemarkerManager.getInstance, but also all of the *Factory.getInstance methods you might have used in version 1. In version 2 most of the factory classes have been removed. You should replace your calls to their getInstance methods with a property for setting the instance from Spring as described above. Here's a list of the removed classes:&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;GroupManagerFactory &lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;UserManagerFactory &lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;AvatarManagerFactory &lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;BanManagerFactory &lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;PollManagerFactory &lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;SearchQueryLoggerFactory &lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;StatusLevelManagerFactory &lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;TagManagerFactory &lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;WidgetDAOFactory &lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;span&gt;Work with Containers for Projects and Spaces/Communities&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;Version 2 introduces &lt;em&gt;projects&lt;/em&gt;, which, like spaces (known as communities in Clearspace Community), collect content such as documents, discussions, and blogs. Projects also add tasks as a content type. To organize the conceptually similar projects and spaces, the API was changed to introduce the idea of a &lt;em&gt;container&lt;/em&gt;. The interfaces that represent projects and spaces&amp;nbsp; -- Project and Community&amp;nbsp; -- now inherit from a common JiveContainer interface.&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;In practical terms, this means that some methods taking an instance of the Community interface now take a JiveContainer instance instead. The following code works to get the latest document in either a project or space, for example, because they inherit from JiveContainer and both can contain documents. To see how your code might be affected, search the Javadoc index for occurrences of JiveContainer in method signatures and return types.&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;!--[CodeBlockStart:af984e88-e37c-4f70-9602-98ff7bca4aaa]--&gt;&lt;pre class="jive-pre"&gt;&lt;code class="jive-code"&gt;public Document getLatestDocument(JiveContainer container) {
&amp;nbsp;&amp;nbsp;&amp;nbsp; if (getDocumentCount(container) == 0) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return null;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp; DocumentResultFilter filter = new DocumentResultFilter();
&amp;nbsp;&amp;nbsp;&amp;nbsp; filter.setSortOrder(DocumentResultFilter.DESCENDING);
&amp;nbsp;&amp;nbsp;&amp;nbsp; filter.setSortField(JiveConstants.MODIFICATION_DATE);

&amp;nbsp;&amp;nbsp;&amp;nbsp; // Round down the lower date boundary by 1 day.
&amp;nbsp;&amp;nbsp;&amp;nbsp; filter.setModificationDateRangeMin(ThreadResultFilter
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .roundDate(container.getModificationDate(), 24 * 60 * 60));
&amp;nbsp;&amp;nbsp;&amp;nbsp; filter.setNumResults(10);
&amp;nbsp;&amp;nbsp;&amp;nbsp; Iterable&amp;lt;Document&amp;gt; documents = documentManager.getDocuments(container, filter);
&amp;nbsp;&amp;nbsp;&amp;nbsp; if (documents.iterator().hasNext()) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return documents.iterator().next();
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp;&amp;nbsp; else {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return null;
&amp;nbsp;&amp;nbsp;&amp;nbsp; }
}&lt;/code&gt;&lt;/pre&gt;&lt;!--[CodeBlockEnd:af984e88-e37c-4f70-9602-98ff7bca4aaa]--&gt;&lt;p&gt;By the way, this getLatestDocument method is now exposed by the DocumentManager interface; in version 1 this method was exposed by the Document interface. Methods such as this one were moved as part of a larger effort to migrate such functionality into managers.&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;span&gt;Use Transaction Support When Updating Multiple Tables&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;Version 2 supports &lt;a class="jive-link-external-small" href="http://static.springframework.org/spring/docs/1.2.x/reference/transaction.html#d0e5917"&gt;transaction management through Spring with the @Transactional annotation&lt;/a&gt;. When the work of your code results in updates (including deletes) to data in multiple database tables, supporting &lt;a class="jive-link-external-small" href="http://en.wikipedia.org/wiki/Database_transaction"&gt;transactional behavior&lt;/a&gt; can help to ensure that the updates are made consistently (that is, all of the effected tables are updated or none are).&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;If you're explicitly supporting transactions with @Transactional, you'll need to add an &lt;a class="jive-link-external-small" href="http://en.wikipedia.org/wiki/AspectJ"&gt;AspectJ&lt;/a&gt; compilation step. The AspectJ compiler weaves into your code the support needed to include at load time your transactional method calls in a transaction context.&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;You'll want to add transaction support if your code updates multiple database tables as while executing a method. While the need to support transactions is fairly rare if you're doing all your work through the Clearspace API, keep in mind that your calls to API set* methods might result in database updates. If you're not sure whether your code's work results in database updates, it's not a bad idea probably to add the @Transactional annotation to the method.&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Adding support for transactions is pretty easy. Here's what you do:&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;Add the @Transactional annotation to any methods whose execution might result in updates to multiple tables. The annotation is in the package &lt;a class="jive-link-external-small" href="http://static.springframework.org/spring/docs/2.0.x/api/org/springframework/transaction/annotation/Transactional.html"&gt;org.springframework.transaction.annotation&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;Compile your code with the &lt;a class="jive-link-external-small" href="http://www.eclipse.org/aspectj/doc/released/devguide/ajc-ref.html"&gt;AspectJ compiler&lt;/a&gt;. There are also &lt;a class="jive-link-external-small" href="http://www.eclipse.org/aspectj/doc/released/devguide/antTasks.html"&gt;Ant tasks&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;span&gt;Use Manager Interfaces to Work with Managed Things&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;Much of the Clearspace code was rewritten to clarify (or create) relationships between instances of manager interfaces and instances of what they manage. The result is an API that's more intuitive, but it also might mean changes to your code.&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;In general, methods designed to handle &lt;em&gt;types of things&lt;/em&gt;&amp;nbsp; -- documents, attachments, discussion messages, and so on&amp;nbsp; -- were moved from a "containing" type to a manager type. For example, in version 1 the method getAttachmentCount was exposed by the interfaces BlogPost, Document, and ForumMessage ; each of these could have attachments, and getAttachmentCount was how you got the count of them. In version 2, you get the count of attachments with the AttachmentManager.getAttachmentCount(AttachmentContentResource) method. The AttachmentContentResource is a marker interface extended by BlogPost, Document, ForumMessage, and other things that can have attachments.&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;So in version 2 the rule of thumb, when looking for a way to manage types of things, is to look for a manager of those things.&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;span&gt;Handle Content As XML&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;Version 2 includes significant changes in the way Clearspace handles content. Improving the rich text editor (which blogs, documents, and discussions threads all use) included completely reworking the way that content is handled in conversions between plain text (wiki markup), rich text, and HTML (for previewed and published content).&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;In particular, content is set and received as XML. In version 1, the content-related accessors that get and set content body, subject and so on received and returned String instances. In version 2, these methods handle content as instances of org.w3c.dom.Document. Version 2 interfaces that used content accessor methods&amp;nbsp; -- including Document, PrivateMessage, ForumMessage, BlogPost, and others&amp;nbsp; -- still include methods such as getPlainBody for retrieving content without markup.&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;For plugins that include actions, you can extend JiveActionSupport for several methods helpful in converting content from one format to another.&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;While version 2 features a model for setting and getting content as XML, there's also an exception: the Macro interface render method still returns content as a String. It has to parse as well-formed XML, but it's still a string.&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;span&gt;Other API Changes&lt;/span&gt;&lt;/h3&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;In some cases, methods that took a JiveObject instance now take an instance of an interface that extends JiveObject. The marker interfaces CommentContentResource and AttachmentContentResource were created to indicate an object's support for comments or attachments. Look for these types in the Javadoc index to find out whether you need to update your own code.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;The information above along with more details can be found in the &lt;a class="jive-link-external-small" href="http://www.jivesoftware.com/community/docs/DOC-2060/"&gt;Upgrading Extensions to 2.0 documentation&lt;/a&gt;.&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;/div&gt;&lt;!-- [DocumentBodyEnd:0f846e5e-081f-4f97-8e0b-a277f0d20817] --&gt;</description>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">freemarker</category>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">clearspace</category>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">2.0</category>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">api</category>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">freemarker</category>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">spring</category>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">xml</category>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">java</category>
      <pubDate>Wed, 16 Jul 2008 21:46:18 GMT</pubDate>
      <author>dawn</author>
      <guid>http://www.jivesoftware.com/jivespace/blogs/jivespace/2008/07/16/customization-part-7-using-the-clearspace-api</guid>
      <dc:date>2008-07-16T21:46:18Z</dc:date>
      <clearspace:dateToText>4 months, 2 weeks ago</clearspace:dateToText>
      <clearspace:replyCount>1</clearspace:replyCount>
      <wfw:comment>http://www.jivesoftware.com/jivespace/blogs/jivespace/comment/customization-part-7-using-the-clearspace-api</wfw:comment>
      <wfw:commentRss>http://www.jivesoftware.com/jivespace/blogs/jivespace/feeds/comments?blogPost=1551</wfw:commentRss>
    </item>
    <item>
      <title>Customization Part 2: Upgrading Themes and FTL files</title>
      <link>http://www.jivesoftware.com/jivespace/blogs/jivespace/2008/06/26/customization-part-2-upgrading-themes-and-ftl-files</link>
      <description>&lt;!-- [DocumentBodyStart:0c202b11-5940-4577-8a13-441862b23fee] --&gt;&lt;div class='jive-rendered-content'&gt;&lt;p&gt;This post is the second in a series of blog posts about customizing for Clearspace 2.x. The first post covered general information about &lt;a class="jive-link-external-small" href="http://www.jivesoftware.com/community/blogs/clearspace/2008/06/24/customizations-in-clearspace-2x-part-one/"&gt;Customizations in Clearspace 2.x&lt;/a&gt;. This post continues the series with more information about upgrading themes and FreeMarker template (FTL) files.&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Each new version of Clearspace includes changes to FTL files and version 2 is no exception. Typically these changes are needed to support new or enhanced features. The FTL changelog included with a Clearspace release provides a list of the FTL files that were changed from the previous version. However, changes in version 2 have pretty much touched every template. In most cases these changes require a simple search-and-replace to fix. But some changes are more substantial.&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;The information on upgrading themes suggests an incremental process for making your changes that could save you some aggravation.&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;The following list suggests the tips and best practices for upgrading your templates.&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;When you've overridden existing Clearspace templates (as in a theme), start with new version 2 FTL files that correspond to the version 1 files in your theme. Then, working from your customized version of the version 1 template, transfer your changes to to the version 2 template. Updating the new templates might help you avoid accidentally transferring code from version 1 that no longer works on version 2. This is especially important given that FreeMarker errors are difficult to debug; errors don't show up until run time. Weaving your version 1 changes into the version 2 templates will make the process more systematic.As you copy your changes into the version 2 template, keep in mind the changed items described below. &lt;br/&gt; &lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;The version 1 pages whose templates were community.ftl and main.ftl -- community pages and the home page -- can be easily customized with widgets in version 2. Before you set out to upgrade these pages, take a look at how much of your customization work could be accomplished by using widgets on the version 2 templates. Using widgets might reduce the amount of customization you need to do and greatly reduce any work in future upgrades.&lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;If you've overridden community.ftl and want to upgrade it, note that the template has been split into multiple FTL files. This was done to divide logically what was a very large template.&lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;Replace WebWork directives with their Struts counterparts. Clearspace version 2 replaces WebWork conventions with Struts. This is pretty much just search-and-replace work to replace @ww. (for WebWork) with @s (for Struts) . The following example shows how to update the url directive. Notice that the updated code also omits the includeParams='none' attribute; in Struts 2, which Clearspace version 2 uses, none is the default value for includeParams.Version 1 (supporting WebWork): &lt;br/&gt; &lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;!--[CodeBlockStart:a7224f54-cc1e-4687-9009-994ec95fe54a]--&gt;&lt;pre class="jive-pre"&gt;&lt;code class="jive-code"&gt;&amp;lt;style type="text/css" media="screen"&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; @import "&amp;lt;@ww.url value='/styles/jive-blog.css' includeParams='none'/&amp;gt;";
&amp;lt;/style&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;!--[CodeBlockEnd:a7224f54-cc1e-4687-9009-994ec95fe54a]--&gt;&lt;p&gt;&lt;br/&gt; Version 2 (supporting Struts): &lt;br/&gt; &lt;/p&gt;&lt;!--[CodeBlockStart:6ea1553d-db41-4a52-9216-c40cc349add6]--&gt;&lt;pre class="jive-pre"&gt;&lt;code class="jive-code"&gt;&amp;lt;style type="text/css" media="screen"&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; @import "&amp;lt;@s.url value='/styles/jive-blog.css'/&amp;gt;";
&amp;lt;/style&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;!--[CodeBlockEnd:6ea1553d-db41-4a52-9216-c40cc349add6]--&gt;&lt;p&gt;&lt;br/&gt; &lt;/p&gt;&lt;ul&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;Update calls to APIs that have been consolidated and simplified. Pay attention to the places in a template where code calls methods directly (although, as a best practice, you should avoid calling methods in FTL code and use actions instead). Here's an example in which you'd replace a call to a JiveGlobals methods with a call to JiveResourceResolver:Version 1 (using JiveGlobals ): &lt;br/&gt; &lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;!--[CodeBlockStart:5bcd4515-de7c-4040-b4ef-ade9de1a9681]--&gt;&lt;pre class="jive-pre"&gt;&lt;code class="jive-code"&gt;&amp;lt;@ww.text name="doc.viewer.more_recent_ver.text"&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;@ww.param&amp;gt;&amp;lt;a href="&amp;gt;&amp;lt;/a&amp;gt;"&amp;gt;&amp;lt;/@ww.param&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;@ww.param&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/@ww.param&amp;gt;
&amp;lt;/@ww.text&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;!--[CodeBlockEnd:5bcd4515-de7c-4040-b4ef-ade9de1a9681]--&gt;&lt;p&gt;&lt;br/&gt; Version 2 (using JiveResourceResolver ): &lt;br/&gt; &lt;/p&gt;&lt;!--[CodeBlockStart:1cd88432-e2a4-49c3-88f8-f924adf15287]--&gt;&lt;pre class="jive-pre"&gt;&lt;code class="jive-code"&gt;&amp;lt;@s.text name="doc.viewer.more_recent_ver.text"&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;@s.param&amp;gt;&amp;lt;a href="&amp;gt;&amp;lt;/a&amp;gt;"&amp;gt;&amp;lt;/@s.param&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;@s.param&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/@s.param&amp;gt;
&amp;lt;/@s.text&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;!--[CodeBlockEnd:1cd88432-e2a4-49c3-88f8-f924adf15287]--&gt;&lt;p&gt;&lt;br/&gt; Here's another example where the change was from another class and method, but again to JiveResourceResolver: &lt;br/&gt; Version 1 (using CommunityUtils ): &lt;br/&gt; &lt;/p&gt;&lt;!--[CodeBlockStart:b73b382b-1b93-499a-aea6-20a5dc070e04]--&gt;&lt;pre class="jive-pre"&gt;&lt;code class="jive-code"&gt;&amp;lt;a href="&amp;gt;&amp;lt;/a&amp;gt;?view=documents" 
&amp;nbsp;&amp;nbsp;&amp;nbsp; class="jive-link-more"&amp;gt;&amp;lt;@ww.text name="doc.main.brdcrmb.documents.link" /&amp;gt;&amp;lt;/a&amp;gt; &lt;/code&gt;&lt;/pre&gt;&lt;!--[CodeBlockEnd:b73b382b-1b93-499a-aea6-20a5dc070e04]--&gt;&lt;p&gt;&lt;br/&gt; Version 2 (using JiveResourceResolver ): &lt;br/&gt; &lt;/p&gt;&lt;!--[CodeBlockStart:29967a64-3753-4ae6-ab79-32651c783a42]--&gt;&lt;pre class="jive-pre"&gt;&lt;code class="jive-code"&gt;&amp;lt;a href="&amp;gt;&amp;lt;/a&amp;gt;?view=documents" 
&amp;nbsp;&amp;nbsp;&amp;nbsp; class="jive-link-more"&amp;gt;&amp;lt;@s.text name="doc.main.brdcrmb.documents.link" /&amp;gt;&amp;lt;/a&amp;gt; &lt;/code&gt;&lt;/pre&gt;&lt;!--[CodeBlockEnd:29967a64-3753-4ae6-ab79-32651c783a42]--&gt;&lt;p&gt;&lt;br/&gt; &lt;/p&gt;&lt;ul&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;Update community references to container references. One twist on the API changes means that both projects and communities (also known as "spaces") are represented conceptually as containers. In the version 2 API, the Community and Project interfaces both inherit from JiveContainer. To disambiguate between the projects and communities, you'll need to pass a container &lt;em&gt;type&lt;/em&gt; with your action calls. The actual disambiguation is handled by Clearspace, however, when it intercepts the call before passing it to the action. The net effect is that the action itself receives only the container ID parameter, not the container type. Here's an FTL example:Version 1 (specifying a community by passing its community ID) &lt;br/&gt; &lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;!--[CodeBlockStart:350730f8-e879-4ca8-beb1-4d977f4fd95a]--&gt;&lt;pre class="jive-pre"&gt;&lt;code class="jive-code"&gt;&amp;lt;@ww.action name="community-breadcrumb" executeResult="true" ignoreContextParams="true"&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;@ww.param name="communityID" value="${community.ID?c}" /&amp;gt;
&amp;lt;/@ww.action&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;!--[CodeBlockEnd:350730f8-e879-4ca8-beb1-4d977f4fd95a]--&gt;&lt;p&gt;&lt;br/&gt; Version 2 (specifying a community by passing both its type and its ID) &lt;br/&gt; &lt;/p&gt;&lt;!--[CodeBlockStart:2d17ded7-8acc-4008-aa8a-d36b37c53c49]--&gt;&lt;pre class="jive-pre"&gt;&lt;code class="jive-code"&gt;&amp;lt;@s.action name="community-breadcrumb" executeResult="true" ignoreContextParams="true"&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;@s.param name="containerType" value="${container.objectType?c}" /&amp;gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;@s.param name="container" value="${container.ID?c}" /&amp;gt;
&amp;lt;/@s.action&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;!--[CodeBlockEnd:2d17ded7-8acc-4008-aa8a-d36b37c53c49]--&gt;&lt;p&gt;&lt;br/&gt; &lt;/p&gt;&lt;ul&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;Update code that handles content. This includes code that gets content for display as wiki markup, HTML, and so on. Among the API changes were several designed to streamline and add structure to how you handle content. For example, in version 1, to get content as wiki markup you would have called methods of the message or document or comment itself. In version 2, you pass the content object to a method inherited from JiveActionSupport. These methods include renderToText, renderToHtml, renderSubjectToHtml, and so on. Here's an example using convertToWikiSyntax:Version 1 (using content object method) &lt;br/&gt; &lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;!--[CodeBlockStart:cfb1c117-e79c-41ac-92f2-9cfdb457e4b9]--&gt;&lt;pre class="jive-pre"&gt;&lt;code class="jive-code"&gt;&amp;lt;textarea id="comment-body-edit-${comment.ID?c}" name="body" rows="10"
&amp;nbsp;&amp;nbsp;&amp;nbsp; style="width:100%;font-family:verdana,arial,helvetica,sans-serif;font-size:8pt;"
&amp;nbsp;&amp;nbsp;&amp;nbsp; class="jive-comment-textarea"&amp;gt;${comment.unfilteredBody!?html}&amp;lt;/textarea&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;!--[CodeBlockEnd:cfb1c117-e79c-41ac-92f2-9cfdb457e4b9]--&gt;&lt;p&gt;&lt;br/&gt; Version 2 (using JiveActionSupport method) &lt;br/&gt; &lt;/p&gt;&lt;!--[CodeBlockStart:016ebdac-52d5-4e5d-a220-2d7866b5b864]--&gt;&lt;pre class="jive-pre"&gt;&lt;code class="jive-code"&gt;&amp;lt;textarea id="comment-body-edit-${comment.ID?c}" name="body" rows="10"
&amp;nbsp;&amp;nbsp;&amp;nbsp; style="width:100%;font-family:verdana,arial,helvetica,sans-serif;font-size:8pt;"
&amp;nbsp;&amp;nbsp;&amp;nbsp; class="jive-comment-textarea"&amp;gt;${action.convertToWikiSyntax(comment)!?html}&amp;lt;/textarea&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;!--[CodeBlockEnd:016ebdac-52d5-4e5d-a220-2d7866b5b864]--&gt;&lt;p&gt;&lt;br/&gt; &lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;span&gt;Removed and Renamed FTL Files&lt;/span&gt;&lt;/h3&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;&lt;p&gt;Version 1 FTL File&lt;/p&gt;&lt;/th&gt;&lt;th&gt;&lt;p&gt;Version 2 Change&lt;/p&gt;&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;p&gt;community-document-picker.ftl&lt;/p&gt;&lt;/td&gt;&lt;td&gt;&lt;p&gt;Renamed to container-document-picker.ftl&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;p&gt;community-thread-picker.ftl&lt;/p&gt;&lt;/td&gt;&lt;td&gt;&lt;p&gt;Renamed to container-thread-picker.ftl&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;p&gt;import-callback-communitynntp.ftl&lt;/p&gt;&lt;/td&gt;&lt;td&gt;&lt;p&gt;Removed.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;p&gt;import-directory-error.ftl&lt;/p&gt;&lt;/td&gt;&lt;td&gt;&lt;p&gt;Removed.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;p&gt;import-directory-updatetags.ftl&lt;/p&gt;&lt;/td&gt;&lt;td&gt;&lt;p&gt;Removed.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;p&gt;import-directory.ftl&lt;/p&gt;&lt;/td&gt;&lt;td&gt;&lt;p&gt;Removed.&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;p&gt;datepicker.ftl&lt;/p&gt;&lt;/td&gt;&lt;td&gt;&lt;p&gt;Renamed to datetimepicker.ftl&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;h2&gt;&lt;span&gt;Upgrading Themes&lt;/span&gt;&lt;/h2&gt;&lt;p&gt;Nearly all of your work upgrading themes will focus on upgrading FreeMarker template (FTL) files. The way you build and deploy themes is unchanged from version 1.&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;But wait -- there's more.&lt;/strong&gt; Having said that, the best practice recommendation in version 2 is to use widget-customized pages wherever possible as an alternative to custom FTLs. You can use widgets in more places than in version 1; check out the section on upgrading widgets for more.&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Here's why you should use widgets:&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;You can do with widgets much of what you'd do with custom FTL markup. In addition, you can write logic in Java behind the your widget UI.&lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;Building widgets to support new features is a good deal tidier than adding new FTL files. While custom FTL files override default FTL files, widgets are encapsulated by the plugin deployment model -- essentially sandboxed.&lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;When it's time to upgrade Clearspace, the work needed to upgrade FTL files you've customized would likely be a good deal greater than what's needed to upgrade a widget.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;span&gt;Suggested Upgrade Process&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;Use the following steps as a systematic way to upgrade your themes.&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;ol&gt;&lt;li level="1" type="ol"&gt;&lt;p&gt;Consider which custom FTLs in your themes can be replaced by customizing the page with widgets.&lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ol"&gt;&lt;p&gt;Use jive.devMode Jive property for debugging. By default, Clearspace hides FreeMarker errors in themes. With dev mode on, you'll see them.&lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ol"&gt;&lt;p&gt;Disable themes while upgrading them.&lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ol"&gt;&lt;p&gt;Enable your custom FTL files one at a time. Debugging incrementally will make the process smoother.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;The information above along with more details can be found in the &lt;a class="jive-link-external-small" href="http://www.jivesoftware.com/community/docs/DOC-2060/"&gt;Upgrading Extensions to 2.0 documentation&lt;/a&gt;.&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;/div&gt;&lt;!-- [DocumentBodyEnd:0c202b11-5940-4577-8a13-441862b23fee] --&gt;</description>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">templates</category>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">clearspace</category>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">2.0</category>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">themes</category>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">templates</category>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">freemarker</category>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">ftl</category>
      <pubDate>Fri, 27 Jun 2008 03:37:27 GMT</pubDate>
      <author>dawn</author>
      <guid>http://www.jivesoftware.com/jivespace/blogs/jivespace/2008/06/26/customization-part-2-upgrading-themes-and-ftl-files</guid>
      <dc:date>2008-06-27T03:37:27Z</dc:date>
      <clearspace:dateToText>4 months, 3 weeks ago</clearspace:dateToText>
      <clearspace:replyCount>1</clearspace:replyCount>
      <wfw:comment>http://www.jivesoftware.com/jivespace/blogs/jivespace/comment/customization-part-2-upgrading-themes-and-ftl-files</wfw:comment>
      <wfw:commentRss>http://www.jivesoftware.com/jivespace/blogs/jivespace/feeds/comments?blogPost=1543</wfw:commentRss>
    </item>
    <item>
      <title>Theming in Clearspace 2.0</title>
      <link>http://www.jivesoftware.com/jivespace/blogs/jivespace/2008/05/12/theming-in-clearspace-20</link>
      <description>&lt;!-- [DocumentBodyStart:1a68e272-f4fb-45ec-84df-af21920499ea] --&gt;&lt;div class='jive-rendered-content'&gt;&lt;p&gt;As you know, we changed a few things in our underlying architecture for Clearspace 2.0, including some changes in the Freemarker templates as a result of moving from Webwork to Struts along with some other changes. In this video, Matt Walker, Professional Services Engineer at Jive Software, talks about the process of upgrading existing themes along with plenty of best practices to make your themes more easily upgradeable in the future.&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Matt also did an earlier screencast as an &lt;a class="jive-link-external-small" href="http://www.jivesoftware.com/community/blogs/podcasts/2008/01/17/introduction-to-skinning-clearspace"&gt;Introduction to Skinning Clearspace&lt;/a&gt;, which you might also want to watch along with this video.&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;object data="http://blip.tv/scripts/flash/blipplayer.swf?autoStart=false&amp;amp;file=http://blip.tv/file/get/Samjive-ThemingClearspace178.flv&amp;amp;source=" height="294" type="application/x-shockwave-flash" width="400" wmode="transparent"&gt;&lt;param name="movie" value="http://blip.tv/scripts/flash/blipplayer.swf?autoStart=false&amp;amp;file=http://blip.tv/file/get/Samjive-ThemingClearspace178.flv&amp;amp;source="/&gt;&lt;/object&gt;&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;You can also download the &lt;a class="jive-link-external-small" href="http://blip.tv/file/get/Samjive-ThemingClearspace178.mov"&gt;Quicktime version&lt;/a&gt; (Caution: file is ~200MB), or you can &lt;a class="jive-link-external-small" href="http://blip.tv/file/893313"&gt;watch a larger version&lt;/a&gt; online, which will improve readability of embedded screenshots (recommended). &lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;The entire presentation is also attached below as a PDF file.&lt;/p&gt;&lt;/div&gt;&lt;!-- [DocumentBodyEnd:1a68e272-f4fb-45ec-84df-af21920499ea] --&gt;</description>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">jivespace</category>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">struts</category>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">clearspace</category>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">themes</category>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">customization</category>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">jivespace</category>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">jive_software</category>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">video</category>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">podcast</category>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">struts</category>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">freemarker</category>
      <pubDate>Mon, 12 May 2008 16:58:01 GMT</pubDate>
      <author>dawn</author>
      <guid>http://www.jivesoftware.com/jivespace/blogs/jivespace/2008/05/12/theming-in-clearspace-20</guid>
      <dc:date>2008-05-12T16:58:01Z</dc:date>
      <clearspace:dateToText>6 months, 1 week ago</clearspace:dateToText>
      <clearspace:replyCount>2</clearspace:replyCount>
      <wfw:comment>http://www.jivesoftware.com/jivespace/blogs/jivespace/comment/theming-in-clearspace-20</wfw:comment>
      <wfw:commentRss>http://www.jivesoftware.com/jivespace/blogs/jivespace/feeds/comments?blogPost=1523</wfw:commentRss>
    </item>
    <item>
      <title>Freemarker w/ WebWork Tutorial</title>
      <link>http://www.jivesoftware.com/jivespace/blogs/jivespace/2008/01/31/freemarker-w-webwork-tutorial</link>
      <description>&lt;!-- [DocumentBodyStart:b95ab216-a441-4efc-9d28-8907423b4b1f] --&gt;&lt;div class='jive-rendered-content'&gt;&lt;h3&gt;&lt;span&gt;Configuring your action to use the freemarker result type&lt;/span&gt;&lt;/h3&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;Freemarker views are rendered via the webwork result type freemarker, or by using the dispatcher result type in conjunction Webwork's FreemarkerServlet.&lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;We use the freemarker result type which is defined in xwork-community.xml, so you can simply use it like so:&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;!--[CodeBlockStart:fd0383ed-2d52-49ee-bac7-dc99a9bc9e9d]--&gt;&lt;pre class="jive-pre"&gt;&lt;code class="jive-code jive-xml"&gt;
&lt;span class="jive-xml-tag"&gt;&amp;lt;action name="test" class="package.Test"&amp;gt;&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="jive-xml-tag"&gt;&amp;lt;result name="success" type="freemarker"&amp;gt;&lt;/span&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /templates/testView.ftl
&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span class="jive-xml-tag"&gt;&amp;lt;/result&amp;gt;&lt;/span&gt; 
&lt;span class="jive-xml-tag"&gt;&amp;lt;/action&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;!--[CodeBlockEnd:fd0383ed-2d52-49ee-bac7-dc99a9bc9e9d]--&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;Since freemarker is defined as the default result type, type="freemarker" is not necessary when declaring your action.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;span&gt;Property Resolution&lt;/span&gt;&lt;/h3&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;Your action properties are automatically resolved. FOR EXAMPLE:&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;!--[CodeBlockStart:6bb9ccc1-55bc-433b-b54c-0042ade2a4e0]--&gt;&lt;pre class="jive-pre"&gt;&lt;code class="jive-code"&gt;
${name} will result in stack.findValue("name"), which generally results in action.getName() being executed.
&lt;/code&gt;&lt;/pre&gt;&lt;!--[CodeBlockEnd:6bb9ccc1-55bc-433b-b54c-0042ade2a4e0]--&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;A search process is used to resolve the variable, searching the following scopes in order, until a value is found:&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;!--[CodeBlockStart:93f12035-f344-4858-b404-73f59579810a]--&gt;&lt;pre class="jive-pre"&gt;&lt;code class="jive-code"&gt;
1.) Freemarker Variables 
2.) Webwork Value Stack 
3.) Request Attributes 
4.) Session Attributes 
5.) Servlet Context Attributes
&lt;/code&gt;&lt;/pre&gt;&lt;!--[CodeBlockEnd:93f12035-f344-4858-b404-73f59579810a]--&gt;&lt;p&gt; &lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h3&gt;&lt;span&gt;Objects in the Context&lt;/span&gt;&lt;/h3&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;Webwork objects added to the context&lt;/p&gt;&lt;/li&gt;&lt;ul&gt;&lt;li level="2" type="ul"&gt;&lt;p&gt;&lt;strong&gt;request&lt;/strong&gt; - the current HttpServletRequest &lt;/p&gt;&lt;/li&gt;&lt;li level="2" type="ul"&gt;&lt;p&gt;&lt;strong&gt;response&lt;/strong&gt; - the current HttpServletResponse &lt;/p&gt;&lt;/li&gt;&lt;li level="2" type="ul"&gt;&lt;p&gt;&lt;strong&gt;stack&lt;/strong&gt; - the current OgnlValueStack &lt;/p&gt;&lt;/li&gt;&lt;li level="2" type="ul"&gt;&lt;p&gt;&lt;strong&gt;ognl&lt;/strong&gt; - the OgnlTool instance. This class contains useful methods to execute OGNL expressions against arbitary objects&lt;/p&gt;&lt;/li&gt;&lt;li level="2" type="ul"&gt;&lt;p&gt;&lt;strong&gt;webwork&lt;/strong&gt; ? an instance of FreemarkerWebWorkUtil&lt;/p&gt;&lt;/li&gt;&lt;li level="2" type="ul"&gt;&lt;p&gt;&lt;strong&gt;action&lt;/strong&gt; - the current WebWork action &lt;/p&gt;&lt;/li&gt;&lt;li level="2" type="ul"&gt;&lt;p&gt;&lt;strong&gt;exception&lt;/strong&gt; - optional the Exception instance, if the view is a JSP exception or Servlet exception&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;Jive objects added to the context&lt;/p&gt;&lt;/li&gt;&lt;ul&gt;&lt;li level="2" type="ul"&gt;&lt;p&gt;JiveGlobals&lt;/p&gt;&lt;/li&gt;&lt;li level="2" type="ul"&gt;&lt;p&gt;JiveConstants&lt;/p&gt;&lt;/li&gt;&lt;li level="2" type="ul"&gt;&lt;p&gt;LocaleUtils&lt;/p&gt;&lt;/li&gt;&lt;li level="2" type="ul"&gt;&lt;p&gt;StringUtils&lt;/p&gt;&lt;/li&gt;&lt;li level="2" type="ul"&gt;&lt;p&gt;DateUtils&lt;/p&gt;&lt;/li&gt;&lt;li level="2" type="ul"&gt;&lt;p&gt;SkinUtils&lt;/p&gt;&lt;/li&gt;&lt;li level="2" type="ul"&gt;&lt;p&gt;Permissions&lt;/p&gt;&lt;/li&gt;&lt;li level="2" type="ul"&gt;&lt;p&gt;IMSettingsUtils&lt;/p&gt;&lt;/li&gt;&lt;li level="2" type="ul"&gt;&lt;p&gt;ActionUtils&lt;/p&gt;&lt;/li&gt;&lt;li level="2" type="ul"&gt;&lt;p&gt;RSSActionSupport&lt;/p&gt;&lt;/li&gt;&lt;li level="2" type="ul"&gt;&lt;p&gt;ViewCountManager&lt;/p&gt;&lt;/li&gt;&lt;li level="2" type="ul"&gt;&lt;p&gt;CommunityUtils&lt;/p&gt;&lt;/li&gt;&lt;li level="2" type="ul"&gt;&lt;p&gt;BlogUtils&lt;/p&gt;&lt;/li&gt;&lt;li level="2" type="ul"&gt;&lt;p&gt;FeedUtils&lt;/p&gt;&lt;/li&gt;&lt;li level="2" type="ul"&gt;&lt;p&gt;WikiUtils&lt;/p&gt;&lt;/li&gt;&lt;li level="2" type="ul"&gt;&lt;p&gt;LicenseManager&lt;/p&gt;&lt;/li&gt;&lt;li level="2" type="ul"&gt;&lt;p&gt;DocumentPermHelper&lt;/p&gt;&lt;/li&gt;&lt;li level="2" type="ul"&gt;&lt;p&gt;MessagePermHelper&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;!--[CodeBlockStart:3c77ea1e-d976-408b-a2b0-4a3c2eeecec0]--&gt;&lt;pre class="jive-pre"&gt;&lt;code class="jive-code"&gt;
${JiveGlobals.getJiveProperty(?skin.defaultHeader?)?default(?Community Home?)}
&lt;/code&gt;&lt;/pre&gt;&lt;!--[CodeBlockEnd:3c77ea1e-d976-408b-a2b0-4a3c2eeecec0]--&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;ul&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;In addition, static models and enums can be referenced as so:&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;!--[CodeBlockStart:23704b69-36ec-48e8-97e2-f29f4a904c88]--&gt;&lt;pre class="jive-pre"&gt;&lt;code class="jive-code"&gt;
${statics('com.jivesoftware.community.action.CommunityAction').VIEW_OVERVIEW}
${enums('com.jivesoftware.community.SearchQueryCriteria$SortType').RELEVANCE.key?c}
where ) is replaced with ] and ( is replaced with [
&lt;/code&gt;&lt;/pre&gt;&lt;!--[CodeBlockEnd:23704b69-36ec-48e8-97e2-f29f4a904c88]--&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;/div&gt;&lt;!-- [DocumentBodyEnd:b95ab216-a441-4efc-9d28-8907423b4b1f] --&gt;</description>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">clearspace</category>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">freemarker</category>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">webwork</category>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">tutorial</category>
      <pubDate>Thu, 31 Jan 2008 16:57:59 GMT</pubDate>
      <author>nick</author>
      <guid>http://www.jivesoftware.com/jivespace/blogs/jivespace/2008/01/31/freemarker-w-webwork-tutorial</guid>
      <dc:date>2008-01-31T16:57:59Z</dc:date>
      <clearspace:dateToText>9 months, 3 weeks ago</clearspace:dateToText>
      <wfw:comment>http://www.jivesoftware.com/jivespace/blogs/jivespace/comment/freemarker-w-webwork-tutorial</wfw:comment>
      <wfw:commentRss>http://www.jivesoftware.com/jivespace/blogs/jivespace/feeds/comments?blogPost=1380</wfw:commentRss>
    </item>
    <item>
      <title>The Switch to Freemarker</title>
      <link>http://www.jivesoftware.com/jivespace/blogs/jivespace/2007/07/20/the-switch-to-freemarker</link>
      <description>&lt;!-- [DocumentBodyStart:a29a66a2-0dae-46eb-8238-1c09f1aaa6bf] --&gt;&lt;div class='jive-rendered-content'&gt;&lt;p&gt;Where are all the JSP's? That is a question we have been hearing a lot lately, after deciding that the view layer of Clearspace would be built on an open alternative to JSP, Freemarker. What is Freemarker? &lt;a class="jive-link-external-small" href="http://freemarker.org"&gt;Freemarker&lt;/a&gt; is simply a "template engine"; a generic tool to generate text output based on tempaltes. The next question that usually follows: &lt;strong&gt;Why?&lt;/strong&gt;&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4&gt;&lt;span&gt;Common problems with JSP&lt;/span&gt;&lt;/h4&gt;&lt;ul&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;Java code is too tempting, even though it is considered bad design to mix presentation with core logic, everyone knowingly does it.&lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;Java code is required to do mundane things, such as &amp;amp;lt;a href="&amp;amp;lt;%= request.getContextPath() %&amp;gt;/index.html"&amp;amp;gt;Home page&amp;amp;lt;/a&amp;amp;gt;&lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;Simple tasks are difficult, such as escaping html, or formatting a date&lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;Looping is verbose, awkward and messy&lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;Bad exception handling, printing out things like NullPointerExceptions to the user&lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;Need a compiler and any change needs to be recompiled.&lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;Various application server bugs. We have recently run into a few problems on 'unnamed' application servers where&amp;nbsp; the jsp's are created importing the servlet package without fully qualifying names, This causes us to have class name problems.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4&gt;&lt;span&gt;Freemarker as an alternative&lt;/span&gt;&lt;/h4&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;To fully realize the benefits of the &lt;a class="jive-link-external-small" href="http://en.wikipedia.org/wiki/Model-view-controller"&gt;MVC Pattern&lt;/a&gt;, a true separation of Java Code (the controller) and the HTML (the view) is required. Using a template engine, such as Freemarker, as your view will solve many of the problems listed above. The underlying design will be cleaner, the syntax clearer, the error messages more meaningful, and the application more customizable.&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Also, Unlike JSP, FreeMarker templates are completely independent of the file format; they can just as easily be used to create an HTML file, XML file, CSS file, JavaScript file, even a plain text file. In fact, FreeMarker is independent of servlets altogether, making it just as useful on the client as on the server.&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;As an example of how Freemarker can cleanup your view pages, lets take one line of JSP and convert it to freemarker:&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;table&gt;&lt;tr&gt;&lt;th&gt;&lt;p&gt;JSP&lt;/p&gt;&lt;/th&gt;&lt;th&gt;&lt;p&gt;Freemarker&lt;/p&gt;&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;p&gt;&amp;amp;lt;% Action action = ActionUtils.getAction(); %&amp;amp;gt; &lt;/p&gt;&lt;p&gt;&amp;amp;lt;input type="text" name="subject" &lt;/p&gt;&lt;p&gt;value="&amp;amp;lt;%= action.getSubject() != null ? StringUtils.escapeHTMLTags(action.getSubject()) : "" %&amp;amp;gt; "/&amp;amp;gt;&lt;/p&gt;&lt;/td&gt;&lt;td&gt;&lt;p&gt;&amp;amp;lt;input type="text" name="subject" &lt;/p&gt;&lt;p&gt;value="${subject!?html}"/&amp;amp;gt;&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;h4&gt;&lt;span&gt;Interesting Clearspace features relating to Freemarker&lt;/span&gt;&lt;/h4&gt;&lt;ul&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;&lt;strong&gt;Themes:&lt;/strong&gt; To help facilitate our customer's need to customize the look and feel of our products, we wrote a feature that provides our customer's the ability to customize most front end pages directly from the admin console without having to make a single change to the source code or even restart the application server. Simply select the page you want to customize and edit the template. Additionally, these custom pages can be grouped into different "Themes" and mapped to a commuity, a forum, even a URL pattern. This type of flexible UI would not be possible with JSP's. Freemarker provides us the ability to load the source of a template from a number of places, including a remote server, and without ever needing to be recompiled.&lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;&lt;strong&gt;Community Everywhere:&lt;/strong&gt; If you want to make some dynamic HTML content available on any remote site, such as displaying a Clearspace thread at the bottom of a remote article, all you have to do is process the freemarker template that contains the thread HTML, wrap it in document.write(result); and return contentType text/javascript.&lt;/p&gt;&lt;/li&gt;&lt;li level="1" type="ul"&gt;&lt;p&gt;&lt;strong&gt;Freemarker Email Templates:&lt;/strong&gt; Allows for easily customizable dynamic emails with very detailed and useful information.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;After using Freemarker for some time, we can definitely say that it is a template language we?re confident in. We found it to be the easiest to use, learn and the most powerful while still having a clean, simple syntax. For a comparision with velocity, check out &lt;a class="jive-link-external-small" href="http://freemarker.org/fmVsVel.html"&gt;Freemarker vs. Velocity&lt;/a&gt;. We?ve also found that any good JSP programmer finds Freemarker enjoyable to use and learn. The one downside is that we all use Intellij Idea for development and there is currently no Freemarker support.&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;For those who still are not convinced, rest assured that it is still possible to make customizations to the application using only JSP's.&lt;/p&gt;&lt;p style="min-height: 8pt; height: 8pt; padding: 0px;"&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;To learn more, check out &lt;a class="jive-link-external-small" href="http://www.javaworld.com/jw-01-2001/jw-0119-freemarker.html?page=1"&gt;FreeMarker: An open alternative to JSP&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;&lt;!-- [DocumentBodyEnd:a29a66a2-0dae-46eb-8238-1c09f1aaa6bf] --&gt;</description>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">clearspace</category>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">clearspacex</category>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">freemarker</category>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">ui</category>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">themes</category>
      <category domain="http://www.jivesoftware.com/jivespace/blogs/jivespace/tags">jsp</category>
      <pubDate>Fri, 20 Jul 2007 16:20:00 GMT</pubDate>
      <author>nick</author>
      <guid>http://www.jivesoftware.com/jivespace/blogs/jivespace/2007/07/20/the-switch-to-freemarker</guid>
      <dc:date>2007-07-20T16:20:00Z</dc:date>
      <clearspace:dateToText>1 year, 4 months ago</clearspace:dateToText>
      <clearspace:replyCount>1</clearspace:replyCount>
      <wfw:comment>http://www.jivesoftware.com/jivespace/blogs/jivespace/comment/the-switch-to-freemarker</wfw:comment>
      <wfw:commentRss>http://www.jivesoftware.com/jivespace/blogs/jivespace/feeds/comments?blogPost=1014</wfw:commentRss>
    </item>
  </channel>
</rss>

