<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Sysbliss Blog</title>
	
	<link>http://blog.sysbliss.com</link>
	<description>On the never-ending quest for systems bliss</description>
	<lastBuildDate>Wed, 20 Jan 2010 20:44:35 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/sysblissblog" /><feedburner:info uri="sysblissblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:feedFlare href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Ffeeds.feedburner.com%2Fsysblissblog" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Fsysblissblog" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare href="http://feeds.my.aol.com/add.jsp?url=http%3A%2F%2Ffeeds.feedburner.com%2Fsysblissblog" src="http://o.aolcdn.com/favorites.my.aol.com/webmaster/ffclient/webroot/locale/en-US/images/myAOLButtonSmall.gif">Subscribe with My AOL</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/http://feeds.feedburner.com/sysblissblog" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Fsysblissblog" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Fsysblissblog" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Fsysblissblog" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><item>
		<title>Atlassian® as a Web-App Framework</title>
		<link>http://feedproxy.google.com/~r/sysblissblog/~3/hcy6pLJIfs0/atlassian-as-a-web-app-framework.html</link>
		<comments>http://blog.sysbliss.com/general-dev/atlassian-as-a-web-app-framework.html#comments</comments>
		<pubDate>Thu, 31 Dec 2009 18:11:04 +0000</pubDate>
		<dc:creator>jdoklovic</dc:creator>
				<category><![CDATA[General Development]]></category>
		<category><![CDATA[atlassian]]></category>

		<guid isPermaLink="false">http://blog.sysbliss.com/?p=107</guid>
		<description><![CDATA[News Flash: I&#8217;m a big fan of Atlassian&#174;.
Not only are all of their apps highly useful, but they are, for the most part, pretty consistent when it comes to installation and plugin management.
Essentially, you extract a zip of the app, edit a [app-name]-init.properties file and include a path where you&#8217;d like the app&#8217;s home directory [...]]]></description>
			<content:encoded><![CDATA[<p>News Flash: I&#8217;m a big fan of <a href="http://www.atlassian.com">Atlassian&reg;</a>.</p>
<p>Not only are all of their apps highly useful, but they are, for the most part, pretty consistent when it comes to installation and plugin management.</p>
<p>Essentially, you extract a zip of the app, edit a [app-name]-init.properties file and include a path where you&#8217;d like the app&#8217;s home directory to live, and start the app. At this point, the app is running with some pre-bundled plugins and provides a plugins folder within the specified home directory where you can drop in new plugins.</p>
<p>Simple.</p>
<p>Now if you&#8217;re like me, at some point you&#8217;ll think that it would be pretty awesome if there was an easy way to make your own webapps behave in this same way including full spring support, auto-home directory creation, bundled plugins, etc, etc.</p>
<p>Lucky for you, I&#8217;ve done all the ground work, and I&#8217;ve packaged it up into something I call the Atlas Webapp Kit</p>
<div class='stb-info_box' >Although I&#8217;ve called it the Atlas Webapp Kit, I am in no way associated with Atlassian&reg;.<br />
This Project is solely a result of my own tinkering.</div>
<h3>Source</h3>
<p>The result of this project will be a war file that can be used as a starting point to build an Atlassian&reg;-like webapp.</p>
<p>The source code can be checked out from subversion:</p>
<pre>svn co http://svn.sysbliss.com/public/atlassian-webappkit/trunk</pre>
<p>Alternatively, you can <a href="http://www.sysbliss.com/downloads/atlas-webappkit-webapp-1.0-src.tar.gz">download a source gzip file.</a></p>
<p>Lastly, you can <a href="http://www.sysbliss.com/downloads/atlas-webappkit-webapp-1.0.war">download a binary of the war file.</a></p>
<h3>Project Structure</h3>
<p>The project is structured as a maven multi-module project with a parent module and two children:</p>
<ul>
<li><strong>atlas-webappkit</strong> &#8211; the parent pom
<ul>
<li><strong>atlas-webappkit-core</strong> &#8211; all of the java code for the app</li>
<li><strong>atlas-webappkit-webapp</strong> &#8211; the webapp descriptors and such</li>
</ul>
</li>
</ul>
<h3>The Parent POM</h3>
<p>Rather than waste bits by listing the parent pom, just take a look at it&#8217;s source.<br />
It&#8217;s pretty basic in that it lists our child modules, sets up dependency and plugin versions and lists the repositories needed.<br />
That&#8217;s it.</p>
<h3>The Webapp</h3>
<p><img src="http://blog.sysbliss.com/wp-content/uploads/2009/12/screenshot_007.png" alt="refplatform-webapp-structure" title="refplatform-webapp-structure" width="352" height="401" class="alignleft size-full wp-image-122"/></p>
<p>We&#8217;re starting with the webapp since it&#8217;s pretty simple and will provide us with some context when we get to the core project.</p>
<p>First let&#8217;s do a quick overview of the files since there are only a few of them:</p>
<ul>
<li><strong>bundled-plugins.xml</strong> &#8211; a simple descriptor used by the maven assembly plugin to zip up any plugins we want to bundle</li>
<li><strong>applicationContextBootstrap.xml</strong> &#8211; a spring beans file for use during the bootstrap process</li>
<li><strong>applicationContextPlugins.xml</strong> &#8211; a spring beans file for initializing the plugins framework</li>
<li><strong>log4j.properties</strong> &#8211; you should know what this is</li>
<li><strong>refplatform-init.properties</strong> &#8211; the properties file that holds our home directory path</li>
<li><strong>context.xml</strong> &#8211; the file to map our url/context in tomcat</li>
<li><strong>web.xml</strong> &#8211; the main web app descriptor</li>
<li><strong>index.jsp</strong> &#8211; just a placeholder jsp</li>
</ul>
<p>Since we are doing a couple of interesting things during the build, I think it&#8217;s worthwhile to have a look at the pom.xml for the webapp module&#8230;.</p>
<p><br clear="all"/></p>
<h3>Webapp POM</h3>
<p>The top of the pom is pretty normal, just inherits the parent pom and sets the project details and so we&#8217;ll skip to the interesting stuff.</p>
<h4>Defining Bundled Plugins</h4>
<p>Lines 23-82 are used to configure the maven-dependency plugin which we&#8217;re using to resolve the plugin artifacts we want to bundle with our app and copy them to the ${pluginBundleDirectory}</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;">            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>maven-dependency-plugin<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;executions<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;execution<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>copy-bundled-plugins<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;phase<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>generate-resources<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/phase<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;goals<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;goal<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>copy<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/goal<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/goals<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;outputDirectory<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>${pluginBundleDirectory}<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/outputDirectory<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactItems<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
                                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactItem<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                                    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.apache.felix<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                                    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.apache.felix.webconsole<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                                    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1.2.10<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactItem<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
                                !!! Others Removed To Save Space !!!
&nbsp;
                            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactItems<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/execution<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/executions<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Lines 84-102 use the maven assembly plugin to create a zip file containing the bundled plugins we just copied and put it in the classpath of the resulting war</p>
<p>Notice on line 87 we specify the <strong>finalName</strong> as atlassian. This will result in our zip file being named atlassian-bundled-plugins.zip<br/>We&#8217;ll need to use this name later to extract the bundle.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;">            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>maven-assembly-plugin<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;finalName<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>atlassian<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/finalName<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;descriptors<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;descriptor<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>src/main/assembly/bundled-plugins.xml<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/descriptor<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/descriptors<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;outputDirectory<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>${project.build.outputDirectory}<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/outputDirectory<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;executions<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;execution<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>create-bundled-plugins<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;phase<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>process-resources<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/phase<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;goals<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;goal<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>attached<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/goal<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/goals<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/execution<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/executions<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>The next section of the full pom sets up cargo for testing and is not listed here.</p>
<h4>Creating our context</h4>
<p>Remember the context.xml file? It&#8217;s used to map our context url to our webapp, however since our final war contains a version number which may change, we need to use some maven &#8220;magic&#8221; to ensure tomcat maps it properly.</p>
<p>Notice our context.xml uses the ${project.version} maven variable</p>
<p><strong>context.xml</strong></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;UTF-8&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Context</span> <span style="color: #000066;">path</span>=<span style="color: #ff0000;">&quot;/atlas-webappkit&quot;</span> <span style="color: #000066;">docBase</span>=<span style="color: #ff0000;">&quot;webapps/atlas-webappkit-webapp-${project.version}&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span></pre></td></tr></table></div>

<p>And on lines 126-141 of our pom, we use the maven-war-plugin to process and filter the context.xml which does the variable substitution for us</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;">             <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                 <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.apache.maven.plugins<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                 <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>maven-war-plugin<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                 <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                     <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;webResources<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                         <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;webResource<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                             <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;directory<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>${basedir}/src/main/webapp/META-INF<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/directory<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                             <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;includes<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                                 <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;include<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>context.xml<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/include<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                             <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/includes<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                             <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;targetPath<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>META-INF<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/targetPath<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                             <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filtering<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>true<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filtering<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                         <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/webResource<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                     <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/webResources<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                 <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
             <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<h4>Dependencies</h4>
<p>Since we&#8217;ve split out all the actual java code to a separate module, our dependency list for the webapp is tiny.<br/>We just need our core jar and log4j</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>145
146
147
148
149
150
151
152
153
154
155
156
157
158
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;">    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependencies<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>com.atlassian.refplatform<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>atlas-webappkit-core<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>${parent.version}<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>log4j<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>log4j<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1.2.9<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependencies<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>And finally, we need to define the <strong>pluginBundleDirectory</strong> property that we used above to bundle plugins.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>160
161
162
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;">    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;properties<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;pluginBundleDirectory<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>target/bundled-plugins<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/pluginBundleDirectory<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/properties<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<h3>The Webapp Descriptor (web.xml)</h3>
<p>Now that our pom is all in order let&#8217;s look at the web.xml file.</p>
<p>The top of the web.xml is pretty standard as it defines the web-app tag and our application name.</p>
<p>Lines 11-16 define our list of Spring beans files we want to load. Notice that we&#8217;re only including the <strong>applicationContextPlugins.xml</strong> and not the bootstrap file.<br/>Also note that this is where you can define any other app-specifc spring files to be loaded.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;UTF-8&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;web-app</span> <span style="color: #000066;">xmlns</span>=<span style="color: #ff0000;">&quot;http://java.sun.com/xml/ns/j2ee&quot;</span></span>
<span style="color: #009900;">             <span style="color: #000066;">xmlns:xsi</span>=<span style="color: #ff0000;">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span>
<span style="color: #009900;">             <span style="color: #000066;">xsi:schemaLocation</span>=<span style="color: #ff0000;">&quot;http://java.sun.com/xml/ns/j2ee</span>
<span style="color: #009900;">         http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd&quot;</span></span>
<span style="color: #009900;">             <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;2.4&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
&nbsp;
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>The Atlassian Reference Application<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;display-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Atlassian RefApp<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/display-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;context-param<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;param-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>contextConfigLocation<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/param-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;param-value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                classpath:/applicationContextPlugins.xml
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/param-value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/context-param<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<h4>Servlet Filters</h4>
<p>Lines 19-62 setup some servlet filters. Each filter uses the class <strong>RefPlatformServletFilterModuleContainerFilter</strong><br/>This filter is used by the Atlassian&reg; Plugins Framework to build a filter chain from any plugins that include servlet filters.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;">    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>filter-plugin-dispatcher-after-encoding<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter-class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>com.atlassian.refplatform.web.servlet.RefPlatformServletFilterModuleContainerFilter<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter-class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;init-param<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;param-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>location<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/param-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;param-value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>after-encoding<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/param-value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/init-param<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>filter-plugin-dispatcher-before-decoration<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter-class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>com.atlassian.refplatform.web.servlet.RefPlatformServletFilterModuleContainerFilter<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter-class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;init-param<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;param-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>location<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/param-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;param-value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>before-decoration<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/param-value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/init-param<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
&nbsp;
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>filter-plugin-dispatcher-before-dispatch<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter-class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>com.atlassian.refplatform.web.servlet.RefPlatformServletFilterModuleContainerFilter<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter-class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;init-param<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;param-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>location<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/param-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;param-value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>before-dispatch<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/param-value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/init-param<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
&nbsp;
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter-mapping<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>filter-plugin-dispatcher-after-encoding<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;url-pattern<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>/*<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/url-pattern<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter-mapping<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter-mapping<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>filter-plugin-dispatcher-before-decoration<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;url-pattern<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>/*<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/url-pattern<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter-mapping<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
&nbsp;
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter-mapping<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;filter-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>filter-plugin-dispatcher-before-dispatch<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;url-pattern<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>/*<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/url-pattern<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/filter-mapping<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<h4>Listeners</h4>
<p>Lines 64-73 setup 2 listeners. The first listener is a bootstrap listener which will be used to load the <strong>applicationContextBootstrap.xml</strong> context and bootstrap the application.<br/>The next listener is a special Spring context loader that will be used to merge our bootstrap context with the rest of the files listed at the top of the web.xml<br/>The second listener is also where we&#8217;ll initialize the plugins framework.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>64
65
66
67
68
69
70
71
72
73
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;">    <span style="color: #808080; font-style: italic;">&lt;!-- ============ Listeners ============== --&gt;</span>
    <span style="color: #808080; font-style: italic;">&lt;!-- Loads the Bootstrap context for minimal app startup --&gt;</span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;listener<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;listener-class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>com.atlassian.refplatform.web.listener.BootstrapLoaderListener<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/listener-class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/listener<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
    <span style="color: #808080; font-style: italic;">&lt;!-- Loads the Spring servlet context if / when the app has been setup --&gt;</span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;listener<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;listener-class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>com.atlassian.refplatform.web.listener.BootstrappedContextLoaderListener<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/listener-class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/listener<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<h4>Servlets and Mappings</h4>
<p>At the end of our web.xml file we define a single servlet and a mapping for it as well as our welcome list.</p>
<p>The servlet is provided by the Atlassian&reg; Plugins Framework and is used to enable any servlets that other plugins may contribute.<br/>The servlet is mapped to <strong>/plugins/servlet/*</strong> This will be the base url where all other plugin servlets will be located.</strong></p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;">    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;servlet<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;servlet-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>plugins<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/servlet-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;servlet-class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>com.atlassian.plugin.servlet.ServletModuleContainerServlet<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/servlet-class<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/servlet<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;servlet-mapping<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;servlet-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>plugins<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/servlet-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;url-pattern<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>/plugins/servlet/*<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/url-pattern<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/servlet-mapping<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
&nbsp;
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;welcome-file-list<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;welcome-file<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>index.jsp<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/welcome-file<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/welcome-file-list<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/web-app<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<h3>Spring Context Files</h3>
<p>The base platform requires 2 spring contexts; One for our bootstrapping process, and the other for the Atlassian&reg; Plugins Framework.</p>
<h4>applicationContextBootstrap.xml</h4>
<p>This file holds all the beans we&#8217;ll need during the bootstrapping process of our application. Since all we need to do during bootstrap is ensure the application&#8217;s home directory exists, this file is rather small.</p>
<p>It&#8217;s also good to note that this file is loaded by the BootstrapLoaderListener servlet listener and not a &#8220;normal&#8221; context loader listener.</p>
<p>In this file we define 2 beans, the homeLocator, and the bootstrapManager that is wired up with the homeLocator. We&#8217;ll get into the specifics of these a bit later.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;">    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;UTF-8&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;beans</span> <span style="color: #000066;">xmlns</span>=<span style="color: #ff0000;">&quot;http://www.springframework.org/schema/beans&quot;</span></span>
<span style="color: #009900;">           <span style="color: #000066;">xmlns:xsi</span>=<span style="color: #ff0000;">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span>
<span style="color: #009900;">           <span style="color: #000066;">xmlns:plugin</span>=<span style="color: #ff0000;">&quot;http://atlassian.com/schema/spring/plugin&quot;</span></span>
<span style="color: #009900;">           <span style="color: #000066;">xsi:schemaLocation</span>=<span style="color: #ff0000;">&quot;</span>
<span style="color: #009900;">           http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd</span>
<span style="color: #009900;">           http://atlassian.com/schema/spring/plugin http://atlassian.com/schema/spring/plugin.xsd&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
&nbsp;
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bean</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;homeLocator&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;com.atlassian.refplatform.core.DefaultHomeLocator&quot;</span> <span style="color: #000066;">plugin:available</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;propertiesFile&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;refplatform-init.properties&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;initPropertyName&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;refplatform.home&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;configFileName&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;refplatform.cfg.xml&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/bean<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
&nbsp;
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bean</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;bootstrapManager&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;com.atlassian.refplatform.web.setup.DefaultBootstrapManager&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;homeLocator&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;ref</span> <span style="color: #000066;">local</span>=<span style="color: #ff0000;">&quot;homeLocator&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/bean<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/beans<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<div class='stb-info_box' >The bootstrap context only contains the required beans to create the home directory.<br />
In a &#8220;real&#8221; app, you may add more beans to this file to handle things like database setup, etc.</div>
<h4>applicationContextPlugins.xml</h4>
<p>This file holds all the beans required by the Atlassian&reg; Plugins Framework and gets loaded by our special BootstrappedContextLoaderListener.</p>
<p>Most of the beans listed in this file are provided by the plugins framework and have to do with iniializing the OSGi system. For that reason, I&#8217;ll only cover the customized beans in this file.</p>
<p>Lines 11-24 define the <strong>pluginManager</strong>. This is a very simple extension of the DefaultPluginManager provided by Atlassian&reg; and is the class used to initialize the entire plugin system.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>11
12
13
14
15
16
17
18
19
20
21
22
23
24
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;">    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bean</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;pluginManager&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;com.atlassian.refplatform.plugins.RefPlatformPluginManager&quot;</span> <span style="color: #000066;">plugin:available</span>=<span style="color: #ff0000;">&quot;true&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;constructor-arg</span> <span style="color: #000066;">index</span>=<span style="color: #ff0000;">&quot;0&quot;</span> <span style="color: #000066;">ref</span>=<span style="color: #ff0000;">&quot;pluginStateStore&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;constructor-arg</span> <span style="color: #000066;">index</span>=<span style="color: #ff0000;">&quot;1&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;list<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;ref</span> <span style="color: #000066;">bean</span>=<span style="color: #ff0000;">&quot;classpathPluginLoader&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;ref</span> <span style="color: #000066;">bean</span>=<span style="color: #ff0000;">&quot;bundledPluginLoader&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;ref</span> <span style="color: #000066;">bean</span>=<span style="color: #ff0000;">&quot;directoryPluginLoader&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/list<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/constructor-arg<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;constructor-arg</span> <span style="color: #000066;">index</span>=<span style="color: #ff0000;">&quot;2&quot;</span> <span style="color: #000066;">ref</span>=<span style="color: #ff0000;">&quot;moduleDescriptorFactory&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;constructor-arg</span> <span style="color: #000066;">index</span>=<span style="color: #ff0000;">&quot;3&quot;</span> <span style="color: #000066;">ref</span>=<span style="color: #ff0000;">&quot;pluginEventManager&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;constructor-arg</span> <span style="color: #000066;">index</span>=<span style="color: #ff0000;">&quot;4&quot;</span> <span style="color: #000066;">ref</span>=<span style="color: #ff0000;">&quot;hostContainer&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;constructor-arg</span> <span style="color: #000066;">index</span>=<span style="color: #ff0000;">&quot;5&quot;</span> <span style="color: #000066;">ref</span>=<span style="color: #ff0000;">&quot;pluginDirectoryLocator&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/bean<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Lines 26-28 define the <strong>pluginDirectoryLocator</strong>. This interface/class provides methods for looking up the various plugin paths that the framework needs. i.e. bundled, plugins, and cache directories.</p>
<p>This is a convenience class that we&#8217;ll use in other beans instead of passing a bunch of strings around.</p>
<div class='stb-info_box' >Note the reference to the homeLocator bean we defined in the previous bootstrap context.</div>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>26
27
28
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;">    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bean</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;pluginDirectoryLocator&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;com.atlassian.refplatform.plugins.DefaultPluginDirectoryLocator&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;constructor-arg</span> <span style="color: #000066;">ref</span>=<span style="color: #ff0000;">&quot;homeLocator&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/bean<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>A little futher down on line 83 we define the <strong>bundledPluginLoader</strong>. This is a factory bean that returns a provided BundledPluginLoader. We have created our own factory here that can make use of our pluginDirectoryLocator.</p>
<p>Note that the last constructor arg is the name of our bundled plugins zip file. If you change the <strong>finalName</strong> property in the pom (maven-seembly-plugin), you&#8217;ll need to update this arg as well.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>83
84
85
86
87
88
89
90
91
92
93
94
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;">    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bean</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;bundledPluginLoader&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;com.atlassian.refplatform.plugins.loader.BundledPluginLoaderFactory&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;constructor-arg</span> <span style="color: #000066;">index</span>=<span style="color: #ff0000;">&quot;0&quot;</span> <span style="color: #000066;">ref</span>=<span style="color: #ff0000;">&quot;pluginDirectoryLocator&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;constructor-arg</span> <span style="color: #000066;">index</span>=<span style="color: #ff0000;">&quot;1&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;list<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;ref</span> <span style="color: #000066;">bean</span>=<span style="color: #ff0000;">&quot;osgiPluginFactory&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;ref</span> <span style="color: #000066;">bean</span>=<span style="color: #ff0000;">&quot;osgiBundleFactory&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;ref</span> <span style="color: #000066;">bean</span>=<span style="color: #ff0000;">&quot;xmlDynamicPluginFactory&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/list<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/constructor-arg<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;constructor-arg</span> <span style="color: #000066;">index</span>=<span style="color: #ff0000;">&quot;2&quot;</span> <span style="color: #000066;">ref</span>=<span style="color: #ff0000;">&quot;pluginEventManager&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;constructor-arg</span> <span style="color: #000066;">index</span>=<span style="color: #ff0000;">&quot;3&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;atlassian-bundled-plugins.zip&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/bean<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Jumping to line 146 we define the servletContextFactory bean. This is just a simple implementation that can be autowired with and return the servletContext.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>146
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;">    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bean</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;servletContextFactory&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;com.atlassian.refplatform.web.servlet.RefPlatformServletContextFactory&quot;</span> <span style="color: #000066;">autowire</span>=<span style="color: #ff0000;">&quot;byType&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span></pre></td></tr></table></div>

<p>Line 150 defines the <strong>hostContainer</strong> This is a class reuiqred by the plugins framework to create and return plugin modules. Our implementation simply pulls them out of the spring context.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>150
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;">    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bean</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;hostContainer&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;com.atlassian.refplatform.plugins.RefPlatformHostContainer&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span></pre></td></tr></table></div>

<p>Finally, lines 154-168 define some string values for use in other beans. All of these strings are created through various spring factory beans.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;">    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bean</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;applicationKey&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;org.springframework.beans.factory.config.FieldRetrievingFactoryBean&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;staticField&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;com.atlassian.refplatform.util.RefPlatformUtils.APPLICATION_KEY&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/bean<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bean</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;pluginDescriptorFilename&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;org.springframework.beans.factory.config.FieldRetrievingFactoryBean&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;staticField&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;com.atlassian.refplatform.plugins.DefaultPluginDirectoryLocator.PLUGIN_DESCRIPTOR&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/bean<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bean</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;pluginCacheDirectory&quot;</span> <span style="color: #000066;">factory-bean</span>=<span style="color: #ff0000;">&quot;pluginDirectoryLocator&quot;</span> <span style="color: #000066;">factory-method</span>=<span style="color: #ff0000;">&quot;getPluginCachesDirectory&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
&nbsp;
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bean</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;pluginDirectory&quot;</span> <span style="color: #000066;">factory-bean</span>=<span style="color: #ff0000;">&quot;pluginDirectoryLocator&quot;</span> <span style="color: #000066;">factory-method</span>=<span style="color: #ff0000;">&quot;getPluginsDirectory&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
&nbsp;
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bean</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;characterEncoding&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;org.springframework.beans.factory.config.FieldRetrievingFactoryBean&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;staticField&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;com.atlassian.refplatform.util.RefPlatformUtils.DEFAULT_CHARACTER_ENCODING&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/bean<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>That wraps up the webapp module. Now on to the core module</p>
<h3>The Core Module</h3>
<p><img src="http://blog.sysbliss.com/wp-content/uploads/2009/12/refplatform-core-structure.png" alt="refplatform-core-structure" title="refplatform-core-structure" width="469" height="801" class="alignleft size-full wp-image-140"/></p>
<p>As you can see, the core module contains a lot of files but don&#8217;t worry as most of these are simply default implementations/extensions of classes provided by the Atlassian&reg; Plugins Framework.</p>
<p>I&#8217;ll save you the excruciatingly boring overview of every file and just jump right to the pom.</p>
<p>This makes the post look a bit uglier, but come on, take the .7 second and scroll dear reader, scroll.</p>
<p><br clear="all"/></p>
<h3>Core POM</h3>
<p>Once again, the top of the pom is pretty normal, just inherits the parent pom and sets the project details.</p>
<h4>Running ANT inside of Maven? This is a joke, right??</h4>
<p>No joke&#8230; On lines 16-44 we&#8217;re including the maven-ant-run plugin and telling it to run the build-utils.ant file located in our etc folder.</p>
<p>This is going to generate a new java source file in our generated-sources folder called <strong>BuildUtils.java</strong></p>
<p>This class will be used by our other classes to grab the version number and build date of our app mainly for logging purposes.</p>
<h4>pom.xml</h4>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;">    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;build<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;plugins<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.apache.maven.plugins<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>maven-antrun-plugin<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;executions<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;execution<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>generate-version-class<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/id<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;phase<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>generate-sources<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/phase<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;goals<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;goal<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>run<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/goal<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/goals<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;tasks<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;ant</span> <span style="color: #000066;">antfile</span>=<span style="color: #ff0000;">&quot;src/main/etc/build-utils.ant&quot;</span> <span style="color: #000066;">inheritAll</span>=<span style="color: #ff0000;">&quot;false&quot;</span> <span style="color: #000066;">inheritRefs</span>=<span style="color: #ff0000;">&quot;false&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
                                    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;version&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;${project.version}&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
                                    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;src.dir&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;${project.build.directory}/generated-sources&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
                                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/ant<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/tasks<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sourceRoot<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                                ${project.build.directory}/generated-sources
                            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sourceRoot<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/configuration<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
                    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/execution<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/executions<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/plugins<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/build<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<h4>etc/build-utils.ant</h4>
<p>The build-utils.ant file is a very simple script that simply echoes a small java source file to our generated-sources folder which will then be compiled by maven.</p>
<p>The script has a single target named generate-version which is the default target. The script expects the version and path to generated-sources to be passed in.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;project</span> <span style="color: #000066;">basedir</span>=<span style="color: #ff0000;">&quot;..&quot;</span> <span style="color: #000066;">default</span>=<span style="color: #ff0000;">&quot;generate-version&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;target</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;generate-version&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;tstamp<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;format</span> <span style="color: #000066;">property</span>=<span style="color: #ff0000;">&quot;build.date&quot;</span> <span style="color: #000066;">pattern</span>=<span style="color: #ff0000;">&quot;MM/dd/yyyy HH:mm:ss&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/tstamp<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;mkdir</span> <span style="color: #000066;">dir</span>=<span style="color: #ff0000;">&quot;${src.dir}/com/atlassian/refplatform/core/util/&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;echo</span> <span style="color: #000066;">file</span>=<span style="color: #ff0000;">&quot;${src.dir}/com/atlassian/refplatform/core/util/BuildUtils.java&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>package com.atlassian.refplatform.core.util;
            /** Automatically generated by ant. */
            public class BuildUtils {
            private static final String VERSION = &quot;${version}&quot;;
            private static final String BUILD_DATE = &quot;${build.date}&quot;;
&nbsp;
            public static String getCurrentBuildDate()
            {
            return BUILD_DATE;
            }
&nbsp;
            public static String getCurrentVersion()
            {
            return VERSION;
            }
&nbsp;
            }
&nbsp;
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/echo<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/target<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/project<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<h4>Core Dependencies</h4>
<p>The rest of our pom just contains the required dependencies for our core project.</p>
<p>These contain the Spring Framework, the Atlassian-Spring bridge, the Atlassian&reg; Plugins Framework and some base plugins we need.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
</pre></td><td class="code"><pre class="xml" style="font-family:monospace;">    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependencies<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>com.atlassian.spring<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>atlassian-spring<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>com.atlassian.plugins<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>atlassian-plugins-core<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>com.atlassian.plugins<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>atlassian-plugins-webfragment<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>com.atlassian.plugins<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>atlassian-plugins-webresource<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>com.atlassian.plugins<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>atlassian-plugins-servlet<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>com.atlassian.plugins<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>atlassian-plugins-osgi<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>com.atlassian.plugins<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>atlassian-plugins-spring<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>javax.servlet<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>servlet-api<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;scope<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>provided<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/scope<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.springframework<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>spring<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.slf4j<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>slf4j-log4j12<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependencies<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></td></tr></table></div>

<p>Onto the code&#8230; I&#8217;ll start with the BootstrapLoaderListener which is the starting point of our app.</p>
<h3>BootstrapLoaderListener</h3>
<p>This class runs when our webapp context is initialized. It&#8217;s responsible for doing any setup that our app needs to run. In our case it ensures our home directory exists, however this is the class to customize if you need to do database setup or other tasks.</p>
<p>Let&#8217;s take a look at the only functional method: contextInitialized:</p>
<p><strong>line 25:</strong> Create a Spring context by loading our applicationContextBootstrap.xml file</p>
<p><strong>line 28:</strong> Bootstrap the app with the help of our BootstrapUtils class.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>30
31
32
33
34
35
36
37
38
39
40
41
</pre></td><td class="code"><pre class="java" style="font-family:monospace;">    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> contextInitialized<span style="color: #009900;">&#40;</span>ServletContextEvent event<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        ApplicationContext bootstrapContext <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ClassPathXmlApplicationContext<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">String</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#123;</span><span style="color: #0000ff;">&quot;applicationContextBootstrap.xml&quot;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span>
            BootstrapUtils.<span style="color: #006633;">init</span><span style="color: #009900;">&#40;</span>bootstrapContext, event.<span style="color: #006633;">getServletContext</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span>BootstrapException e<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            log.<span style="color: #006633;">error</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;An error was encountered while bootstrapping atlas-webappkit (see below): <span style="color: #000099; font-weight: bold;">\n</span>&quot;</span> <span style="color: #339933;">+</span> e.<span style="color: #006633;">getMessage</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>, e<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        startupLog.<span style="color: #006633;">info</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Starting Atlassian RefPlatform &quot;</span> <span style="color: #339933;">+</span> BuildUtils.<span style="color: #006633;">getCurrentVersion</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<h4>BootstrapUtils</h4>
<p>In the previous code, we delegated the bootstrapping to a BootstrapUtils class.</p>
<p>This is a convenience class to encapsulate the initialization of the bootstrapManager and the homeLocator and provides a place to store/retrieve our bootstrap spring context</p>
<p>Not a very interesting class, but the init method is worth reviewing.</p>
<p><strong>line 27:</strong> Get our homeLocator and try to set the home path from the servlet context if available.</p>
<p><strong>line 29:</strong> Store the bootstrap spring context so other classes can get to it easily.</p>
<p><strong>lines 30-35:</strong>Get the bootstrapManager from the context and initialize it.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
</pre></td><td class="code"><pre class="java" style="font-family:monospace;">    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000066; font-weight: bold;">void</span> init<span style="color: #009900;">&#40;</span>ApplicationContext bootstrapContext, ServletContext servletContext<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> BootstrapException
    <span style="color: #009900;">&#123;</span>
        <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>HomeLocator<span style="color: #009900;">&#41;</span>bootstrapContext.<span style="color: #006633;">getBean</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;homeLocator&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">lookupServletHomeProperty</span><span style="color: #009900;">&#40;</span>servletContext<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        setBootstrapContext<span style="color: #009900;">&#40;</span>bootstrapContext<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        BootstrapManager bootstrapManager <span style="color: #339933;">=</span> getBootstrapManager<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>bootstrapManager <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
            <span style="color: #000000; font-weight: bold;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> BootstrapException<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Could not initialise boostrap manager&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        bootstrapManager.<span style="color: #006633;">init</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>bootstrapManager.<span style="color: #006633;">isBootstrapped</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
            <span style="color: #000000; font-weight: bold;">throw</span> <span style="color: #000000; font-weight: bold;">new</span> BootstrapException<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Unable to bootstrap application: &quot;</span> <span style="color: #339933;">+</span> bootstrapManager.<span style="color: #006633;">getBootstrapFailureReason</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<h4>HomeLocator</h4>
<p>It&#8217;s now time to review the HomeLocator. We have the HomeLocator interface and an implementation called DefaultHomeLocator.</p>
<p>This class is responsible for, as it&#8217;s name suggests, locating the application&#8217;s home directory. To do this it looks in the following places in the following order: </p>
<ol>
<li>A System Property named <strong>refplatform.home</strong> (defined in applicationContextBootstrap.xml)</li>
<li>The refplatform.home property defined in <strong>refplatform-init.properties</strong></li>
<li>The refplatform.home property defined as a servletContext init parameter.</li>
</ol>
<p>Since this class simply returns the value found in one of these places and <strong>does not actually create the directory</strong> I won&#8217;t bother listing it&#8217;s contents here.</p>
<h4>BootstrapManager</h4>
<p>Like the HomeLocator, the BootstrapManager is and interface with a DefaultBootstrapManager implementation.</p>
<p>For our purposes, the BootstrapManager is simply responsible for getting the home path from the HomeLocator and creating the directory if it doesn&#8217;t already exist.</p>
<p>We&#8217;ve de-coupled all of this functionality so that custom implementations can be easily provided in case more steps are needed in the bootstrap process.</p>
<p>Again, this class is not listed here since it&#8217;s fairly straightforward. See the source provided for the full details.</p>
<h3>BootstrappedContextLoaderListener</h3>
<p>In the context of running the app, at this point the bootstrap is complete and an empty home directory has been created if needed. Now it&#8217;s time to init the plugin system and load any app-sepcific Spring contexts</p>
<p>This is the function of the BootstrappedContextLoaderListener which is an extension of the provided ContainerContextLoaderListener.</p>
<p>Our custom implementation provides some extra functionality to merge our bootstrap context with the other provided Spring contexts and initializes the plugin system.</p>
<p><strong>lines 28-42</strong> &#8211; canInitialiseContainer: simply ensure we&#8217;ve been bootstrapped before loading the contexts</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
</pre></td><td class="code"><pre class="java" style="font-family:monospace;">    @Override
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">boolean</span> canInitialiseContainer<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        BootstrapManager bootstrapManager <span style="color: #339933;">=</span> BootstrapUtils.<span style="color: #006633;">getBootstrapManager</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>bootstrapManager <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000066; font-weight: bold;">false</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>bootstrapManager.<span style="color: #006633;">isBootstrapped</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000066; font-weight: bold;">false</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
        <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000066; font-weight: bold;">true</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p><strong>lines 44-47</strong> &#8211; override the getNewSpringContainerContext method to return a custom BootstrappedContainerContext (listed later)</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>44
45
46
47
</pre></td><td class="code"><pre class="java" style="font-family:monospace;">    @Override
    <span style="color: #000000; font-weight: bold;">protected</span> SpringContainerContext getNewSpringContainerContext<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000000; font-weight: bold;">new</span> BootstrappedContainerContext<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p><strong>lines 52-55</strong> &#8211; override the createContextLoader method to return a custom BootstrappedContextLoader (listed later)</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>52
53
54
55
</pre></td><td class="code"><pre class="java" style="font-family:monospace;">    @Override
    <span style="color: #000000; font-weight: bold;">public</span> ContextLoader createContextLoader<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000000; font-weight: bold;">new</span> BootstrappedContextLoader<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p><strong>lines 57-65</strong> &#8211; a little more interesting&#8230; Our context is initialized and so we pull our pluginManager bean out of the context and call it&#8217;s init method which kicks off the entire plugin framework initialization</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>58
59
60
61
62
63
64
65
66
</pre></td><td class="code"><pre class="java" style="font-family:monospace;">    @Override
    <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000066; font-weight: bold;">void</span> postInitialiseContext<span style="color: #009900;">&#40;</span>ServletContextEvent event<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">super</span>.<span style="color: #006633;">postInitialiseContext</span><span style="color: #009900;">&#40;</span>event<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        ApplicationContext ctx <span style="color: #339933;">=</span> WebApplicationContextUtils.<span style="color: #006633;">getWebApplicationContext</span><span style="color: #009900;">&#40;</span>event.<span style="color: #006633;">getServletContext</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        RefPlatformPluginManager pluginManager <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>RefPlatformPluginManager<span style="color: #009900;">&#41;</span> ctx.<span style="color: #006633;">getBean</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;pluginManager&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        pluginManager.<span style="color: #006633;">init</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<h4>BootstrappedContainerContext</h4>
<p>This is a simple extension of the provided SpringContainerContext in whic we simply override the refresh method so that we can use our custom BootstrappedContextLoader to reload the application context</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
</pre></td><td class="code"><pre class="java" style="font-family:monospace;">    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">synchronized</span> <span style="color: #000066; font-weight: bold;">void</span> refresh<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        ContextLoader loader <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> BootstrappedContextLoader<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">// if we have an existing spring context, ensure we close it properly</span>
        ApplicationContext ctx <span style="color: #339933;">=</span> WebApplicationContextUtils.<span style="color: #006633;">getWebApplicationContext</span><span style="color: #009900;">&#40;</span>getServletContext<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>ctx <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            loader.<span style="color: #006633;">closeWebApplicationContext</span><span style="color: #009900;">&#40;</span>getServletContext<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        loader.<span style="color: #006633;">initWebApplicationContext</span><span style="color: #009900;">&#40;</span>getServletContext<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>getApplicationContext<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            setApplicationContext<span style="color: #009900;">&#40;</span>WebApplicationContextUtils.<span style="color: #006633;">getWebApplicationContext</span><span style="color: #009900;">&#40;</span>getServletContext<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        contextReloaded<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<h4>BootstrappedContextLoader</h4>
<p>This is a simple extension of the Spring provided ContextLoader class that overrides the loadParentContext and uses our BootstrapUtils class to return our previously loaded bootstrap context. This essentially makes the bootstrap context beans available to all other contexts.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>17
18
19
20
21
</pre></td><td class="code"><pre class="java" style="font-family:monospace;">    @Override
    <span style="color: #000000; font-weight: bold;">protected</span> ApplicationContext loadParentContext<span style="color: #009900;">&#40;</span>ServletContext servletContext<span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> BeansException
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">return</span> BootstrapUtils.<span style="color: #006633;">getBootstrapContext</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<h3>The other custom classes</h3>
<p>During the explanation of the applicationContextPlugins.xml file, I mentioned a few other custom classes that we haven;t covered. Specifically these are:</p>
<ul>
<li>BundledPluginLoaderFactory</li>
<li>RefPlatformHostContainer</li>
<li>RefPlatformPluginManager</li>
</ul>
<p>I&#8217;m not going to go into detail on these classes since they are simple extensions of Atlassian&reg; provided default classes that just add the ability to make use of our PluginDirectoryLocator.</p>
<p>That being said, it is worth covering the PluginDirectoryLocator itself&#8230;</p>
<h4>DefaultPluginDirectoryLocator</h4>
<p>This class is responsible for determining and creating the bundled plugins, user added plugins, and plugins cache directories.</p>
<p>This class gets the homeLocator injected into it to use as the base path for all of the above mentioned folders.</p>
<p>Although the implementation is very simple, I wanted to list it since this is the place you can customize where plugins get added/stored.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
</pre></td><td class="code"><pre class="java" style="font-family:monospace;">    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> BUNDLED_PLUGINS_DIRECTORY <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;bundled-plugins&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> DIRECTORY_PLUGINS_DIRECTORY <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;plugins&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> PLUGIN_CACHES_DIR_NAME <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;caches&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> PLUGIN_DESCRIPTOR <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;atlassian-plugin.xml&quot;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">final</span> HomeLocator homeLocator<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> DefaultPluginDirectoryLocator<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">final</span> HomeLocator homeLocator<span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">homeLocator</span> <span style="color: #339933;">=</span> homeLocator<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">File</span> getPluginsDirectory<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">return</span> getHomeSubDirectory<span style="color: #009900;">&#40;</span>homeLocator, DIRECTORY_PLUGINS_DIRECTORY<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">File</span> getBundledPluginsDirectory<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">return</span> getHomeSubDirectory<span style="color: #009900;">&#40;</span>homeLocator, BUNDLED_PLUGINS_DIRECTORY<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">File</span> getPluginCachesDirectory<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">return</span> getHomeSubDirectory<span style="color: #009900;">&#40;</span>homeLocator, PLUGIN_CACHES_DIR_NAME<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #003399;">String</span> getPluginDescriptorFilename<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">return</span> PLUGIN_DESCRIPTOR<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #003399;">File</span> getHomeSubDirectory<span style="color: #009900;">&#40;</span>HomeLocator homeLocator, <span style="color: #003399;">String</span> subDirectory<span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #003399;">File</span> homePath <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">File</span><span style="color: #009900;">&#40;</span>homeLocator.<span style="color: #006633;">getHomePath</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #003399;">File</span> directory <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">File</span><span style="color: #009900;">&#40;</span>homePath, subDirectory<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>directory.<span style="color: #006633;">exists</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
        <span style="color: #009900;">&#123;</span>
            directory.<span style="color: #006633;">mkdir</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
&nbsp;
        <span style="color: #000000; font-weight: bold;">return</span> directory<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<h3>Non-Used Classes</h3>
<p>In the source tree there are 2 classes that aren&#8217;t currently used.</p>
<ul>
<li>RefPlatformModuleDescriptorFactory</li>
<li>AbstractRefPlatformModuleDescrptor</li>
</ul>
<p>These classes are here in case you want to add &#8220;built-in&#8221; plugins to your app.</p>
<p>To do so, simply replace the</p>
<pre>&lt;bean id="moduleDescriptorFactory" class="com.atlassian.plugin.DefaultModuleDescriptorFactory"&gt;</pre>
<p>in the applicationContextPlugins.xml file with</p>
<pre>&lt;bean id="moduleDescriptorFactory" class="com.atlassian.refplatform.plugins.descriptor.RefPlatformModuleDescriptorFactory"&gt;</pre>
<p>In the RefPlatformModuleDescriptorFactory you can then add any custom module descriptors you want to provide to your app</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">    <span style="color: #000000; font-weight: bold;">public</span> RefPlatformModuleDescriptorFactory<span style="color: #009900;">&#40;</span>HostContainer hostContainer<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">super</span><span style="color: #009900;">&#40;</span>hostContainer<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">//you can add any custom plugins here:</span>
        <span style="color: #666666; font-style: italic;">// addModuleDescriptor(&quot;myCustomPlugin&quot;,MyCustomModuleDescriptor.class);</span>
    <span style="color: #009900;">&#125;</span></pre></div></div>

<p>Each module descriptor you add should extend AbstractRefPlatformModuleDescriptor</p>
<p>For a (very) little more on module descriptors, see: <a href="http://confluence.atlassian.com/display/PLUGINFRAMEWORK/Quick+Start+Guide+to+Embedding">http://confluence.atlassian.com/display/PLUGINFRAMEWORK/Quick+Start+Guide+to+Embedding</a></p>
<h3>Building the app</h3>
<p>So now that we have all the build and source files, you should be able to easily build and run this with a few short maven steps:</p>
<ol>
<li>Run the <strong>install</strong> goal on atlas-webappkit-core</li>
<li>Run the <strong>package</strong> goal on atlas-webappkit-webapp</li>
<li>Run the <strong>cargo:start</strong> goal on atlas-webappkit-webapp</li>
</ol>
<p>After cargo starts up you&#8217;ll be able to see the junk jsp at http://localhost:8080/atlas-webappkit/index.jsp</p>
<p>Added bonus&#8230; you can access the <a href="http://felix.apache.org/site/apache-felix-web-console.html">Felix Web Console</a> at http://localhost:8080/atlas-webappkit/plugins/servlet/system/console/</p>
<h3>Topics Not Covered</h3>
<p>At this point you now have an app that can bootstrap itself, create a home directory, create the plugin directories, extract any bundled plugins, load the bundled plugins, load user added plugins, and process any Spring files. HOORAY!</p>
<p>There are however a few things not covered by this post that I&#8217;m going to leave for other posts or for you to figure out on your own:</p>
<ul>
<li>Assembling a zipped tomcat with the war already exploded and ready to run</li>
<li>Enabling the webapp to show a first-time setup wizard</li>
<li>Using AMPS to build plugins for your custom app</li>
<li>Adding other various Atlassian&reg; plugins (i.e. rest support)</li>
</ul>
<p>Although the above topics were left out, I hope you&#8217;ve found this post helpful.</p>
<p>As always, any comments, suggestions or improvements are very welcomed.</p>
<img src="http://feeds.feedburner.com/~r/sysblissblog/~4/hcy6pLJIfs0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.sysbliss.com/general-dev/atlassian-as-a-web-app-framework.html/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		<feedburner:origLink>http://blog.sysbliss.com/general-dev/atlassian-as-a-web-app-framework.html</feedburner:origLink></item>
		<item>
		<title>Testing Atlassian Rest Plugins</title>
		<link>http://feedproxy.google.com/~r/sysblissblog/~3/iivreawwkm4/testing-atlassian-rest-plugins.html</link>
		<comments>http://blog.sysbliss.com/development-process/testing-atlassian-rest-plugins.html#comments</comments>
		<pubDate>Fri, 30 Oct 2009 15:52:39 +0000</pubDate>
		<dc:creator>jdoklovic</dc:creator>
				<category><![CDATA[atlassian]]></category>
		<category><![CDATA[development process]]></category>

		<guid isPermaLink="false">http://blog.sysbliss.com/?p=66</guid>
		<description><![CDATA[With the latest versions of the Atlassian products, you can now add your own rest component plugins.
This is really cool, however, while testing rest plugins is actually pretty easy, figuring out exactly how to do it can drive a person crazy.  And so I thought I&#8217;d write this post in hopes of saving others [...]]]></description>
			<content:encoded><![CDATA[<p>With the latest versions of the Atlassian products, you can now add your own rest component plugins.</p>
<p>This is really cool, however, while testing rest plugins is actually pretty easy, figuring out exactly how to do it can drive a person crazy.  And so I thought I&#8217;d write this post in hopes of saving others hours of research time.</p>
<h2>The Project</h2>
<p>For this example we&#8217;re just going to create a really simple rest resource that returns a list of the projects in JIRA.<br />
I&#8217;m not going to walk through plugin development step-by-step but I&#8217;ll get us started&#8230;</p>
<h3>Create a project</h3>
<p>Let&#8217;s create our project using the <a href="http://confluence.atlassian.com/display/DEVNET/How+to+Build+an+Atlassian+Plugin+using+the+Atlassian+Plugin+SDK;jsessionid=B33CD1C757846C639741360C570D244A">Atlassian Plugin SDK</a>.<br />
Just open a terminal and navigate to your base workspace folder. Then run:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">atlas-create-jira-plugin</pre></div></div>

<p>When asked for the plugin name, call it <strong>jira-projects-rest</strong></p>
<h3>Add some Maven Dependencies</h3>
<p>We&#8217;ll need a few libraries to help us test, just add the following to the pom dependency list</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;">        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>javax.ws.rs<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>jsr311-api<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1.0<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;scope<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>provided<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/scope<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>javax.xml.bind<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>jaxb-api<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>2.1<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;scope<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>provided<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/scope<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>com.atlassian.plugins.rest<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>atlassian-rest-common<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1.0.2<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;scope<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>provided<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/scope<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>javax.servlet<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>servlet-api<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>2.3<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;scope<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>provided<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/scope<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>com.sun.jersey<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/groupId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>jersey-test-framework<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/artifactId<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>1.1.2-ea<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;scope<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>test<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/scope<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
	<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/dependency<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<h3>Add the rest descriptor</h3>
<p>Once the project is created, edit the atlassian-plugin.xml and add our rest component:</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;atlassian-plugin</span> <span style="color: #000066;">key</span>=<span style="color: #ff0000;">&quot;${project.groupId}.${project.artifactId}&quot;</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;${project.artifactId}&quot;</span> <span style="color: #000066;">plugins-version</span>=<span style="color: #ff0000;">&quot;2&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;plugin-info<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>${project.description}<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>${project.version}<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/version<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;vendor</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;${project.organization.name}&quot;</span> <span style="color: #000066;">url</span>=<span style="color: #ff0000;">&quot;${project.organization.url}&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;application-version</span> <span style="color: #000066;">min</span>=<span style="color: #ff0000;">&quot;4.0&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bundle-instructions<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;Import-Package<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>org.apache.commons.collections,*;resolution:=optional<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/Import-Package<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/bundle-instructions<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/plugin-info<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;rest</span> <span style="color: #000066;">key</span>=<span style="color: #ff0000;">&quot;projectsService&quot;</span> <span style="color: #000066;">path</span>=<span style="color: #ff0000;">&quot;/projectfinder&quot;</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Provides a service that lists JIRA projects<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/rest<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;component</span> <span style="color: #000066;">key</span>=<span style="color: #ff0000;">&quot;projectFinder&quot;</span></span>
<span style="color: #009900;">        <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;Project Finder&quot;</span></span>
<span style="color: #009900;">        <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;com.sysbliss.jira.plugins.util.ProjectFinder&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
&nbsp;
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/atlassian-plugin<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<h3>The guts</h3>
<p>So in the plugin descriptor you&#8217;ll notice we have a component named &#8220;projectFinder&#8221;.<br />
This is a simple helper class that&#8217;s not really required, but it helps to decouple our service wrapper and would make sense in a more complex plugin.</p>
<p>The ProjectFinder is responsible for looking up and returning our project list:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
</pre></td><td class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">com.sysbliss.jira.plugins.util</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.util.ArrayList</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.util.Collection</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.util.Collections</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.util.List</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">com.atlassian.jira.project.Project</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">com.atlassian.jira.project.ProjectManager</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> ProjectFinder <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">final</span> ProjectManager projectManager<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> ProjectFinder<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">final</span> ProjectManager projectManager<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">projectManager</span> <span style="color: #339933;">=</span> projectManager<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> List<span style="color: #339933;">&lt;</span>Project<span style="color: #339933;">&gt;</span> getProjects<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	List<span style="color: #339933;">&lt;</span>Project<span style="color: #339933;">&gt;</span> projects <span style="color: #339933;">=</span> projectManager.<span style="color: #006633;">getProjectObjects</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>projects <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	    projects <span style="color: #339933;">=</span> <span style="color: #003399;">Collections</span>.<span style="color: #339933;">&lt;</span>Project<span style="color: #339933;">&gt;</span> emptyList<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">return</span> projects<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<h3>The service wrapper</h3>
<p>So now we need a service wrapper. This basically contains 2 classes:</p>
<ul>
<li><strong>ProjectsResource</strong> &#8211; The class that will be our jersey Resource</li>
<li><strong>RestProject</strong> &#8211; a JAXB class that represents a single project</li>
</ul>
<h4>ProjectsResource.java</h4>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
</pre></td><td class="code"><pre class="java" style="font-family:monospace;">&nbsp;
<span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">com.sysbliss.jira.plugins.rest</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.util.ArrayList</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.util.List</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.ws.rs.GET</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.ws.rs.Path</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.ws.rs.Produces</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.ws.rs.core.MediaType</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.ws.rs.core.Response</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">com.atlassian.jira.project.Project</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">com.atlassian.plugins.rest.common.security.AnonymousAllowed</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">com.sysbliss.jira.plugins.util.ProjectFinder</span><span style="color: #339933;">;</span>
&nbsp;
@Path<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;&quot;</span><span style="color: #009900;">&#41;</span>
@Produces<span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#123;</span> MediaType.<span style="color: #006633;">APPLICATION_JSON</span>, MediaType.<span style="color: #006633;">APPLICATION_XML</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> ProjectsResource <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">final</span> ProjectFinder projectFinder<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> ProjectsResource<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">final</span> ProjectFinder projectFinder<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">projectFinder</span> <span style="color: #339933;">=</span> projectFinder<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    @GET
    @Path<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;projects&quot;</span><span style="color: #009900;">&#41;</span>
    @AnonymousAllowed
    @Produces<span style="color: #009900;">&#40;</span> <span style="color: #009900;">&#123;</span> MediaType.<span style="color: #006633;">APPLICATION_JSON</span>, MediaType.<span style="color: #006633;">APPLICATION_XML</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #000000; font-weight: bold;">public</span> Response getProjects<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">final</span> List<span style="color: #339933;">&lt;</span>Project<span style="color: #339933;">&gt;</span> projectList <span style="color: #339933;">=</span> projectFinder.<span style="color: #006633;">getProjects</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000000; font-weight: bold;">final</span> List<span style="color: #339933;">&lt;</span>RestProject<span style="color: #339933;">&gt;</span> restProjectList <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ArrayList<span style="color: #339933;">&lt;</span>RestProject<span style="color: #339933;">&gt;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">final</span> Project project <span style="color: #339933;">:</span> projectList<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	    restProjectList.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> RestProject<span style="color: #009900;">&#40;</span>project.<span style="color: #006633;">getName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">final</span> GenericEntity<span style="color: #339933;">&lt;</span>List<span style="color: #339933;">&lt;</span>RestProject<span style="color: #339933;">&gt;&gt;</span> entities <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> GenericEntity<span style="color: #339933;">&lt;</span>List<span style="color: #339933;">&lt;</span>RestProject<span style="color: #339933;">&gt;&gt;</span><span style="color: #009900;">&#40;</span>restProjectList<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">return</span> Response.<span style="color: #006633;">ok</span><span style="color: #009900;">&#40;</span>entities<span style="color: #009900;">&#41;</span>.<span style="color: #006633;">build</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Let&#8217;s move on to the RestProject that represents a JIRA project.<br />
For this example, I&#8217;m just going to include the name field, but you could add all the other stuff if needed.</p>
<h4>RestProject.java</h4>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
</pre></td><td class="code"><pre class="java" style="font-family:monospace;">&nbsp;
<span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">com.sysbliss.jira.plugins.rest</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.xml.bind.annotation.XmlElement</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.xml.bind.annotation.XmlRootElement</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">net.jcip.annotations.Immutable</span><span style="color: #339933;">;</span>
&nbsp;
@Immutable
@XmlRootElement
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> RestProject <span style="color: #009900;">&#123;</span>
&nbsp;
    @XmlElement
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> name<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> RestProject<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">name</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&quot;&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> RestProject<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> name<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">this</span>.<span style="color: #006633;">name</span> <span style="color: #339933;">=</span> name<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<h2>Unit Testing</h2>
<p><strong>Although I gave you the implementation code first, this was actually written test-first and I highly advise all others to do the same</strong></p>
<p>At this point if all is well, we have a simple rest service in JIRA that returns a list containing RestProject objects.<br />
The first thing we want to test is our ProjectFinder class. These will be <strong>unit tests</strong>.</p>
<p>Since we will need to mock out JIRA Project objects, it&#8217;s handy to write a little test utility for that.<br />
<em>Note: All the test classes use the <a href="http://mockito.org/">Mockito framework</a> for making mocks.</em></p>
<h4>ProjectMockUtils.java</h4>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
</pre></td><td class="code"><pre class="java" style="font-family:monospace;">&nbsp;
<span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">com.sysbliss.jira.plugins.test.util</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">static</span> org.<span style="color: #006633;">mockito</span>.<span style="color: #006633;">Mockito</span>.<span style="color: #006633;">mock</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">static</span> org.<span style="color: #006633;">mockito</span>.<span style="color: #006633;">Mockito</span>.<span style="color: #006633;">when</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.util.Collection</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">com.atlassian.jira.project.Project</span><span style="color: #339933;">;</span>
&nbsp;
&nbsp;
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> ProjectMockUtils <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> Project createMockProject<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">Long</span> id, <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> name, <span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> key<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">final</span> Project project <span style="color: #339933;">=</span> mock<span style="color: #009900;">&#40;</span>Project.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	when<span style="color: #009900;">&#40;</span>project.<span style="color: #006633;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">thenReturn</span><span style="color: #009900;">&#40;</span>id<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	when<span style="color: #009900;">&#40;</span>project.<span style="color: #006633;">getName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">thenReturn</span><span style="color: #009900;">&#40;</span>name<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	when<span style="color: #009900;">&#40;</span>project.<span style="color: #006633;">getKey</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">thenReturn</span><span style="color: #009900;">&#40;</span>key<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">return</span> project<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>And now on to the unit tests. These are pretty simple and shouldn&#8217;t require too much explanation&#8230;<br />
<em>Note: The unit tests are using the <a href="http://testng.org/doc/index.html">TestNG framework</a>.</em></p>
<h4>ProjectFinderTest.java</h4>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
</pre></td><td class="code"><pre class="java" style="font-family:monospace;">&nbsp;
<span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">com.sysbliss.jira.plugins</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">static</span> org.<span style="color: #006633;">mockito</span>.<span style="color: #006633;">Matchers</span>.<span style="color: #006633;">anyLong</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">static</span> org.<span style="color: #006633;">mockito</span>.<span style="color: #006633;">Matchers</span>.<span style="color: #006633;">eq</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">static</span> org.<span style="color: #006633;">mockito</span>.<span style="color: #006633;">Mockito</span>.<span style="color: #006633;">mock</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">static</span> org.<span style="color: #006633;">mockito</span>.<span style="color: #006633;">Mockito</span>.<span style="color: #006633;">when</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.util.ArrayList</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.util.List</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.testng.annotations.Test</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">com.atlassian.jira.project.Project</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">com.atlassian.jira.project.ProjectManager</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">com.sysbliss.jira.plugins.test.util.ProjectMockUtils</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">com.sysbliss.jira.plugins.util.ProjectFinder</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> ProjectFinderTest <span style="color: #009900;">&#123;</span>
&nbsp;
    @Test
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> projectsAreFound<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">final</span> List<span style="color: #339933;">&lt;</span>Project<span style="color: #339933;">&gt;</span> projects <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ArrayList<span style="color: #339933;">&lt;</span>Project<span style="color: #339933;">&gt;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	projects.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span>ProjectMockUtils.<span style="color: #006633;">createMockProject</span><span style="color: #009900;">&#40;</span>1L, <span style="color: #0000ff;">&quot;Project 1&quot;</span>, <span style="color: #0000ff;">&quot;PRJ1&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	projects.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span>ProjectMockUtils.<span style="color: #006633;">createMockProject</span><span style="color: #009900;">&#40;</span>2L, <span style="color: #0000ff;">&quot;Project 2&quot;</span>, <span style="color: #0000ff;">&quot;PRJ2&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">final</span> ProjectManager projectManager <span style="color: #339933;">=</span> mock<span style="color: #009900;">&#40;</span>ProjectManager.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	when<span style="color: #009900;">&#40;</span>projectManager.<span style="color: #006633;">getProjectObjects</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">thenReturn</span><span style="color: #009900;">&#40;</span>projects<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">final</span> ProjectFinder finder <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ProjectFinder<span style="color: #009900;">&#40;</span>projectManager<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">final</span> List<span style="color: #339933;">&lt;</span>Project<span style="color: #339933;">&gt;</span> found <span style="color: #339933;">=</span> finder.<span style="color: #006633;">getProjects</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">assert</span> found.<span style="color: #006633;">size</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">2</span> <span style="color: #339933;">:</span> <span style="color: #0000ff;">&quot;Expected 2 projects but got &quot;</span> <span style="color: #339933;">+</span> found.<span style="color: #006633;">size</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>So that&#8217;s that.  I&#8217;m keeping it to that one method for this example. In real life, you&#8217;d have a bunch of boundry tests, etc, etc.</p>
<p>Next, and equally as exciting, almost the same exact test for the resource wrapper.</p>
<h4>ProjectsResourceTest.java</h4>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
</pre></td><td class="code"><pre class="java" style="font-family:monospace;">&nbsp;
<span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">com.sysbliss.jira.plugins</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">static</span> org.<span style="color: #006633;">mockito</span>.<span style="color: #006633;">Mockito</span>.<span style="color: #006633;">mock</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">static</span> org.<span style="color: #006633;">mockito</span>.<span style="color: #006633;">Mockito</span>.<span style="color: #006633;">when</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.util.ArrayList</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.util.List</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.ws.rs.core.Response</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">org.testng.annotations.Test</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">com.atlassian.jira.project.Project</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">com.atlassian.jira.project.ProjectManager</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">com.sysbliss.jira.plugins.rest.RestProject</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">com.sysbliss.jira.plugins.rest.ProjectsResource</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">com.sysbliss.jira.plugins.test.util.ProjectMockUtils</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">com.sysbliss.jira.plugins.util.ProjectFinder</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> ProjectsResourceTest <span style="color: #009900;">&#123;</span>
&nbsp;
    @Test
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> resourceProjectsAreFound<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">final</span> List<span style="color: #339933;">&lt;</span>Project<span style="color: #339933;">&gt;</span> projects <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ArrayList<span style="color: #339933;">&lt;</span>Project<span style="color: #339933;">&gt;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	projects.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span>ProjectMockUtils.<span style="color: #006633;">createMockProject</span><span style="color: #009900;">&#40;</span>1L, <span style="color: #0000ff;">&quot;Project 1&quot;</span>, <span style="color: #0000ff;">&quot;PRJ1&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	projects.<span style="color: #006633;">add</span><span style="color: #009900;">&#40;</span>ProjectMockUtils.<span style="color: #006633;">createMockProject</span><span style="color: #009900;">&#40;</span>2L, <span style="color: #0000ff;">&quot;Project 2&quot;</span>, <span style="color: #0000ff;">&quot;PRJ2&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">final</span> ProjectManager projectManager <span style="color: #339933;">=</span> mock<span style="color: #009900;">&#40;</span>ProjectManager.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	when<span style="color: #009900;">&#40;</span>projectManager.<span style="color: #006633;">getProjectObjects</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">thenReturn</span><span style="color: #009900;">&#40;</span>projects<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">final</span> ProjectFinder finder <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ProjectFinder<span style="color: #009900;">&#40;</span>projectManager<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">final</span> ProjectsResource resource <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ProjectsResource<span style="color: #009900;">&#40;</span>finder<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">final</span> Response response <span style="color: #339933;">=</span> resource.<span style="color: #006633;">getProjects</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">final</span> GenericEntity<span style="color: #339933;">&lt;</span>List<span style="color: #339933;">&lt;</span>RestProject<span style="color: #339933;">&gt;&gt;</span> entities <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>GenericEntity<span style="color: #339933;">&lt;</span>List<span style="color: #339933;">&lt;</span>RestProject<span style="color: #339933;">&gt;&gt;</span><span style="color: #009900;">&#41;</span> response.<span style="color: #006633;">getEntity</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">final</span> List<span style="color: #339933;">&lt;</span>RestProject<span style="color: #339933;">&gt;</span> restProjects <span style="color: #339933;">=</span> entities.<span style="color: #006633;">getEntity</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">assert</span> <span style="color: #009900;">&#40;</span>restProjects.<span style="color: #006633;">size</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">2</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">:</span> <span style="color: #0000ff;">&quot;Expected 2 projects but got &quot;</span> <span style="color: #339933;">+</span> restProjects.<span style="color: #006633;">size</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>The above test is a little more interesting in the fact that it&#8217;s using our jersey resource to test that our resource classes are working properly and that we are getting the correct model objects from the Response class.</p>
<p>So that&#8217;s it for the unit tests. Pretty simple and doesn&#8217;t require any external connections to anything.<br />
On to the interesting parts&#8230;.</p>
<h2>Integration Testing</h2>
<p>The new <a href="http://confluence.atlassian.com/display/DEVNET/How+to+Build+an+Atlassian+Plugin+using+the+Atlassian+Plugin+SDK;jsessionid=B33CD1C757846C639741360C570D244A">Atlassian Plugins SDK</a> provides some really cool stuff to help with integration testing and coupled with a few little &#8220;tricks&#8221; it&#8217;s pretty painless.</p>
<h3>The Goal</h3>
<p>The goal of our integration test harness is to deploy our plugin into a running JIRA instance, provide a known set of data, and actually make http requests to our new resource to verify that everything is working properly.</p>
<p>Before we can get started writing our test, we need to do a little setup.</p>
<h3>Creating a dataset</h3>
<p>We&#8217;re going to need a known set of data in our JIRA instance; namely, 2 empty projects.<br />
The first step in creating the data is to boot up JIRA. Once again, the plugins SDK makes this easy&#8230;.</p>
<h4>Running JIRA</h4>
<p>In a terminal, navigate to the project root and run:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">atlas-run</pre></div></div>

<p>If you&#8217;ve never run this previously, get some coffee&#8230;.  maven&#8217;s going to do some web surfing for a while.<br />
Once maven has completed, the SDK will boot up JIRA and deploy our plugin. At this point, we don&#8217;t really care about our rest resource&#8230;.  we&#8217;re just going to make use of JIRA.</p>
<p>So now just open a browser and point it at: <em>http://localhost:2990/jira</em></p>
<p>This will bring up JIRA and put you at the dashboard.  Login using admin/admin as user/pass.</p>
<h4>Create Projects</h4>
<p>Finally, go to the JIRA administration section and create 2 projects.  It doesn&#8217;t matter what they&#8217;re called, and they don&#8217;t need to have any issues or anything, <strong>just be sure there are 2 and only 2 projects created.</strong></p>
<p>After the projects are created, use the backup to xml tool to export the data to an xml file.<br />
The file should be saved as: <strong>[project-root]/src/test/xml/it-data.xml</strong></p>
<p>That&#8217;s it. Now just CTRL-C in the terminal to shutdown JIRA.</p>
<h3>Test Properties</h3>
<p>We&#8217;re going to be making use of the JiraWebTest class (more on that in a bit) which requires us to make a properties file for integration testing.</p>
<p>Create a file: <strong>[project-root]/src/test/resources/localtest.properties</strong><br />
The contents of the file should be:</p>

<div class="wp_syntax"><div class="code"><pre class="properties" style="font-family:monospace;"><span style="color: #000080; font-weight:bold;">jira.protocol</span> <span style="color: #000000;">=</span><span style="color: #008000; font-weight:bold;"> http</span>
<span style="color: #000080; font-weight:bold;">jira.host</span> <span style="color: #000000;">=</span><span style="color: #008000; font-weight:bold;"> localhost</span>
<span style="color: #000080; font-weight:bold;">jira.port</span> <span style="color: #000000;">=</span><span style="color: #008000; font-weight:bold;"> 2990</span>
<span style="color: #000080; font-weight:bold;">jira.context</span> <span style="color: #000000;">=</span><span style="color: #008000; font-weight:bold;"> /jira</span>
<span style="color: #000080; font-weight:bold;">jira.edition</span> <span style="color: #000000;">=</span><span style="color: #008000; font-weight:bold;"> all</span>
<span style="color: #808080; font-style: italic;"># Please note jira.xml.data.location needs to be the full path</span>
<span style="color: #000080; font-weight:bold;">jira.xml.data.location</span> <span style="color: #000000;">=</span><span style="color: #008000; font-weight:bold;"> src/test/xml/</span>
&nbsp;
<span style="color: #000080; font-weight:bold;">jira.release.info</span> <span style="color: #000000;">=</span><span style="color: #008000; font-weight:bold;"> unknown</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #808080; font-style: italic;"># If the browser path is set then when a test fails the func test framework will try and start</span>
<span style="color: #808080; font-style: italic;"># the browser with a temporary file of captured web output.  if its not set then no harm</span>
<span style="color: #808080; font-style: italic;"># and System.out will be used to dump the web response.</span>
<span style="color: #808080; font-style: italic;">#</span>
<span style="color: #000080; font-weight:bold;">browser.path</span><span style="color: #000000;">=</span><span style="color: #008000; font-weight:bold;">firefox</span></pre></div></div>

<p>Now our integration harness setup is complete and we can finally move on to the interesting stuff.</p>
<h3>The Test Suite</h3>
<p>Since we&#8217;re going to make use of the JiraWebTest, we are forced to use JUnit for the integration tests.<br />
This requires us to create a JUnit Test Suite which is liste below.</p>
<p><em>Note: ALL integration tests must be in a test package that starts with <strong>it.</strong>[rest.of.package]</em></p>
<h4>AllTests.java</h4>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code"><pre class="java" style="font-family:monospace;">&nbsp;
<span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">it.com.sysbliss.jira.plugins</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">junit.framework.Test</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">junit.framework.TestSuite</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> AllTests <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> Test suite<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">final</span> TestSuite suite <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> TestSuite<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Integration Test for it.com.sysbliss.jira.plugins&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	suite.<span style="color: #006633;">addTestSuite</span><span style="color: #009900;">&#40;</span>ProjectsRestTest.<span style="color: #000000; font-weight: bold;">class</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">return</span> suite<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<h3>What&#8217;s this JiraWebTest anyway?</h3>
<p>JiraWebTest is a class provided by the jira-func-test package that should have been added to your pom.xml by the plugins SDK when you created the project.</p>
<p>It&#8217;s a class that your test classes can extend that provides extra functionality when running integration tests.<br />
That extra functionality comes at a price though, like being forced to use JUnit&#8230;  But wait, that&#8217;s not all! <a href="http://blogs.atlassian.com/developer/2008/01/sharpening_our_functional_test.html">You can read an entire post about the pros and cons of the web test framework.</a></p>
<p>That being said, we are going to make as little use of this class as possible in hope something better comes along, however it does provide something very useful: <strong>The ability to load our exported test data.</strong></p>
<p>And so, we&#8217;ll put up with it for now.</p>
<h3>Finally, the integration test!</h3>
<p>So here I&#8217;ll just proved the entire class and provide explanations after it.</p>
<h4>ProjectsRestTest.java</h4>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
</pre></td><td class="code"><pre class="java" style="font-family:monospace;">&nbsp;
<span style="color: #000000; font-weight: bold;">package</span> <span style="color: #006699;">it.com.sysbliss.jira.plugins</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.io.ByteArrayInputStream</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.io.InputStream</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.xml.bind.JAXBContext</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">javax.xml.bind.Unmarshaller</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">com.sun.jersey.api.client.Client</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">com.sun.jersey.api.client.GenericType</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">com.sun.jersey.api.client.WebResource</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">com.atlassian.jira.webtests.JIRAWebTest</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">com.sysbliss.jira.plugins.rest.RestProject</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">com.sysbliss.jira.plugins.rest.RestProjects</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> ProjectsRestTest <span style="color: #000000; font-weight: bold;">extends</span> JIRAWebTest <span style="color: #009900;">&#123;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> ProjectsRestTest<span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">final</span> <span style="color: #003399;">String</span> name<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">super</span><span style="color: #009900;">&#40;</span>name<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    @Override
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> setUp<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">super</span>.<span style="color: #006633;">setUp</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	restoreData<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;it-data.xml&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    @Override
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> tearDown<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">super</span>.<span style="color: #006633;">tearDown</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> testRestProjectsFound<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">throws</span> <span style="color: #003399;">Exception</span> <span style="color: #009900;">&#123;</span>
	<span style="color: #000000; font-weight: bold;">final</span> Client client <span style="color: #339933;">=</span> Client.<span style="color: #006633;">create</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000000; font-weight: bold;">final</span> WebResource resource <span style="color: #339933;">=</span> client.<span style="color: #006633;">resource</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;http://localhost:2990/jira/rest/projectversions/1.0/projects.xml&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #000000; font-weight: bold;">final</span> List<span style="color: #339933;">&lt;</span>RestProject<span style="color: #339933;">&gt;</span> projects <span style="color: #339933;">=</span> resource.<span style="color: #006633;">get</span><span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">new</span> GenericType<span style="color: #339933;">&lt;</span>List<span style="color: #339933;">&lt;</span>RestProject<span style="color: #339933;">&gt;&gt;</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	assertEquals<span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">2</span>, projects.<span style="color: #006633;">size</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<h4>Extend JiraWebTest</h4>
<p><strong>line 18:</strong><br />
we simply extend JiraWebTest to give us our data loading functionality</p>
<p><strong>line 21:</strong><br />
make sure you call super() !</p>
<p><strong>lines 24-28:</strong></p>
<ul>
<li>override the setUp method</li>
<li>call super.setUp()</li>
<li>call restoreData(&#8220;it-data.xml&#8221;); &#8211; this loads our test data before each test</li>
</ul>
<p><strong>lines 30-33:</strong><br />
Make sure you override tearDown and call super.tearDown();</p>
<p><strong>lines 36-37:</strong></p>
<ul>
<li>create a jersey Client</li>
<li>create a WebResource with our resource url</li>
</ul>
<p><strong>line 39:</strong><br />
Execute our GET request and cast the response to our model using the GenericType provided by jax-rs</p>
<p><strong>line 40:</strong><br />
We can now use our model objects to assert that our request returned the 2 project objects we have in our test data.</p>
<h3>Running the tests</h3>
<p>whew, we&#8217;re finally ready to actually run the tests&#8230;  plugins SDK anyone?</p>
<p>Drop out to a terminal in the project root and run:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">atlas-integration-test</pre></div></div>

<p>Sit back and enjoy as you watch the following whiz (well, maybe half-walk/half-jog) by you:</p>
<ul>
<li>Project is compiled and unit tests are run</li>
<li>JIRA is started and the plugin is automatically deployed</li>
<li>admin logs into JIRA and imports our test data</li>
<li>we are welcomed to the Hotel California</i>
<li>framework verifys JIRA is ready to run the integration tests</li>
<li>The integration tests are run</li>
<li>JIRA shuts down</li>
</ul>
</h4>
<p>The crowd rejoices</h4>
<p>Although this article is a bit verbose, once you set this up, doing it again for other projects is a breeze and the feeling you get seeing the &#8220;build successful&#8221; at the end never get old.</p>
<p>Hope this was helpful&#8230;</p>
<img src="http://feeds.feedburner.com/~r/sysblissblog/~4/iivreawwkm4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.sysbliss.com/development-process/testing-atlassian-rest-plugins.html/feed</wfw:commentRss>
		<slash:comments>13</slash:comments>
		<feedburner:origLink>http://blog.sysbliss.com/development-process/testing-atlassian-rest-plugins.html</feedburner:origLink></item>
		<item>
		<title>Build System Installer</title>
		<link>http://feedproxy.google.com/~r/sysblissblog/~3/L5Tzw-i4Uzs/build-system-installer.html</link>
		<comments>http://blog.sysbliss.com/development-process/build-system-installer.html#comments</comments>
		<pubDate>Mon, 06 Apr 2009 18:01:55 +0000</pubDate>
		<dc:creator>jdoklovic</dc:creator>
				<category><![CDATA[development process]]></category>

		<guid isPermaLink="false">http://blog.sysbliss.com/?p=56</guid>
		<description><![CDATA[Later this week I&#8217;ll be posting a full tutorial on setting up and using the sysbliss automated build system.
For now, you can download the repository installer and poke around if you wish.
To install, download and extract the tar.gz file.  Move the extracted contents to the webserver you wish to use for your repository and run [...]]]></description>
			<content:encoded><![CDATA[<p>Later this week I&#8217;ll be posting a full tutorial on setting up and using the sysbliss automated build system.</p>
<p>For now, you can download the repository installer and poke around if you wish.</p>
<p>To install, download and extract the tar.gz file.  Move the extracted contents to the webserver you wish to use for your repository and run ant -f sysbliss-repo-installer.xml</p>
<p>Just follow the prompts and your repo will be setup.</p>
<p>More on using the system later.</p>
<p><a href="http://blog.sysbliss.com/sysbliss-repo-installer.tar.gz">Download Sysbliss Repo Installer</a></p>
<img src="http://feeds.feedburner.com/~r/sysblissblog/~4/L5Tzw-i4Uzs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.sysbliss.com/development-process/build-system-installer.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://blog.sysbliss.com/development-process/build-system-installer.html</feedburner:origLink></item>
		<item>
		<title>Release Management with Atlassian Bamboo and Jira</title>
		<link>http://feedproxy.google.com/~r/sysblissblog/~3/QeKYicQgu1g/release-management-with-atlassian-bamboo-and-jira.html</link>
		<comments>http://blog.sysbliss.com/uncategorized/release-management-with-atlassian-bamboo-and-jira.html#comments</comments>
		<pubDate>Mon, 04 Aug 2008 16:48:15 +0000</pubDate>
		<dc:creator>jdoklovic</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[development process]]></category>

		<guid isPermaLink="false">http://blog.sysbliss.com/?p=9</guid>
		<description><![CDATA[I recently released a new plugin for <a title="Atlassian Bamboo" href="http://www.atlassian.com/software/bamboo/">Atlassian Bamboo</a> called <a title="Jira Versions Bamboo Plugin" href="http://confluence.atlassian.com/display/BAMEXT/JiraVersions+Plugin">Jira Versions</a>.
In combination with <a title="Jira - Bug Tracking Software" href="http://www.atlassian.com/software/jira/">Jira</a>, the <a title="Bamboo Tagger Plugin" href="http://confluence.atlassian.com/display/BAMEXT/Bamboo+Tagger+plugin">Bamboo Tagger Plugin</a> and the <a title="Pre-Post Build Command Plugin" href="http://confluence.atlassian.com/display/BAMEXT/Pre-Post+Build+Command+Plugin">Pre/Post Build Command Plugin</a> it can be used as a complete release management system. [...]]]></description>
			<content:encoded><![CDATA[<p>I recently released a new plugin for <a title="Atlassian Bamboo" href="http://www.atlassian.com/software/bamboo/">Atlassian Bamboo</a> called <a title="Jira Versions Bamboo Plugin" href="http://confluence.atlassian.com/display/BAMEXT/JiraVersions+Plugin">Jira Versions</a>.<br />
In combination with <a title="Jira - Bug Tracking Software" href="http://www.atlassian.com/software/jira/">Jira</a>, the <a title="Bamboo Tagger Plugin" href="http://confluence.atlassian.com/display/BAMEXT/Bamboo+Tagger+plugin">Bamboo Tagger Plugin</a> and the <a title="Pre-Post Build Command Plugin" href="http://confluence.atlassian.com/display/BAMEXT/Pre-Post+Build+Command+Plugin">Pre/Post Build Command Plugin</a> it can be used as a complete release management system.</p>
<p>This post serves both as a quick tutorial on setting up bamboo as a release management system as well as a scenario that illustrates how the plugins can be used within a release workflow.</p>
<h2>Scenario</h2>
<h3>Project Information</h3>
<p>In our scenario, we will be building a fictitious web app project.<br />
This project will be using an iterative/agile development process.<br />
We will have:</p>
<ul>
<li>3 development iterations</li>
<li>2 release candidates</li>
<li>1 production release</li>
<li>1 emergency bugfix release.</li>
</ul>
<p><strong>Bamboo Project Information:</strong></p>
<table border="1" cellpadding="2">
<tbody>
<tr>
<td><strong><span style="color: #000000;">Project Name</span></strong></td>
<td>Web Apps</td>
</tr>
<tr>
<td><strong>Project Key</strong></td>
<td>WEB</td>
</tr>
<tr>
<td><strong>Plan Name</strong></td>
<td>My Web App</td>
</tr>
<tr>
<td><strong>Plan Key</strong></td>
<td>MYAPP</td>
</tr>
</tbody>
</table>
<h3>Deployment</h3>
<p>Since we&#8217;re building a webapp, we need to deployment workflow for when and where different builds get deployed.<br />
Figure A. shows our <em>logical</em> deployment workflow. The actual physical deployment all happens from the Bamboo server via shell scripts.</p>
<dl id="attachment_10" class="wp-caption alignnone" style="width: 244px;">
<dt class="wp-caption-dt"><a rel="lightbox" href="http://blog.sysbliss.com/wp-content/uploads/2008/08/logical_release_deploy.png"><img class="size-medium wp-image-10" title="logical_release_deploy" src="http://blog.sysbliss.com/wp-content/uploads/2008/08/logical_release_deploy-234x300.png" alt="Figure A: Logical Release Deployment" width="234" height="300" /></a></dt>
</dl>
<dl id="attachment_10" class="wp-caption alignnone" style="width: 244px;">
<dt class="wp-caption-dt"> <em>Figure A. Logical Release Deployment </em></dt>
</dl>
<h3>Versioning</h3>
<p>Our project will use the following version number scheme:</p>
<p>[Major].[Minor].[Bugfix]-[type][iteration]-[build]</p>
<table border="1">
<tbody>
<tr>
<td><strong>Major</strong></td>
<td>the major release number</td>
</tr>
<tr>
<td><strong>Minor</strong></td>
<td>new features backwards compatible</td>
</tr>
<tr>
<td><strong>Bugfix</strong></td>
<td>maintenance fixes / emergency</td>
</tr>
<tr>
<td><strong>type</strong></td>
<td>release level i.e. dev, rc, prod</td>
</tr>
<tr>
<td><strong>iteration</strong></td>
<td>iteration number</td>
</tr>
<tr>
<td><strong>build</strong></td>
<td>bamboo build key / number</td>
</tr>
</tbody>
</table>
<p>Using this scheme, our project will produce the following final version numbers (with multiple build versions in-between)</p>
<ul>
<li>1.0.0-dev1 &#8211; development iteration 1</li>
<li>1.0.0-dev2 &#8211; development iteration 2</li>
<li>1.0.0-dev3 &#8211; development iteration 3</li>
<li>1.0.0-rc1 &#8211; release candidate 1</li>
<li>1.0.0-rc2 &#8211; release candidate 2</li>
<li>1.0.0 &#8211; first production release</li>
<li>1.0.1 &#8211; emergency production bugfix release</li>
</ul>
<h2>Installation</h2>
<p>Installation is simple&#8230;.<br />
Assuming you already have Jira and Bamboo installed and running:</p>
<p>Just download the 3 distrubution jars from the respective plugin pages and drop them into your ${BAMBOO_INSTALL}/webapp/WEB-INF/lib folder.</p>
<ul>
<li><a title="Jira Versions Bamboo Plugin" href="http://confluence.atlassian.com/display/BAMEXT/JiraVersions+Plugin">Jira Versions Plugin</a></li>
<li><a title="Bamboo Tagger Plugin" href="http://confluence.atlassian.com/display/BAMEXT/Bamboo+Tagger+plugin">Bamboo Tagger Plugin</a></li>
<li><a title="Pre-Post Build Command Plugin" href="http://confluence.atlassian.com/display/BAMEXT/Pre-Post+Build+Command+Plugin">Pre-Post Build Command Plugin</a></li>
</ul>
<p>now just restart bamboo.</p>
<h2>Project Setup</h2>
<h3>Version Your Package</h3>
<p>Most software built today is compiled and packaged with some sort of automated tool. I&#8217;m sure there are a few die-hards that are still using vi and javac on the command-line but for the rest of us not living in the eighties, we&#8217;re using something like ant, maven, etc.</p>
<p>To that end, the jiraversions plugin was written to be compatible with almost every automated builder known today. This is accomplished by the use of parameters that can be passed to the builder of choice via the command-line. (how that gets done will be discussed shortly).</p>
<p>So the first thing we need to do is setup our build script to figure out which version it&#8217;s building and use it as part of the package name.</p>
<p><span style="color: #808080;"><em>note: for simplicity&#8217;s sake, I&#8217;m going to use Ant in the examples, but the same method can be applied to anything that can run via a command line. I&#8217;m also going to use java as the language of choice, but again, bamboo and the plugins mentioned in this post can be used to build anything.</em></span></p>
<p>Assuming you already have targets that compile and jar up your project, we just need to add a target that gets the current version for the build and sets it as a property that can be used to append to the name of your jar file.</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;target</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;get-version&quot;</span> <span style="color: #000066;">unless</span>=<span style="color: #ff0000;">&quot;version.name&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;tstamp<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;format</span> <span style="color: #000066;">property</span>=<span style="color: #ff0000;">&quot;build.time&quot;</span> <span style="color: #000066;">pattern</span>=<span style="color: #ff0000;">&quot;yyyyMMdd_HHmmss&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/tstamp<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;version.name&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;${user.name}-${build.time}&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;version.type&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;user&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;version.released&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;false&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/target<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>Essentially this target is here to handle builds done on a local developer&#8217;s machine.<br />
It&#8217;s saying that if version.name was not passed on the commandline (or set some other way) then set default version properties.<br />
The most interesting property is the version.name which will be set to the user&#8217;s username and a timestamp.<br />
i.e. if I do a build on my local machine, the version will look something like: jdoklovic-2008-Aug-01_130923</p>
<p>Now we need to make sure that our final artifact is named properly. Usually you&#8217;ll have some sort of package target that handles spitting out the final artifact.<br />
In our case the packaging looks like this:</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;target</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;package&quot;</span> <span style="color: #000066;">depends</span>=<span style="color: #ff0000;">&quot;create-war&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
&nbsp;
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;target</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;create-war&quot;</span> <span style="color: #000066;">depends</span>=<span style="color: #ff0000;">&quot;compile,get-version&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;warfile&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;${ant.project.name}-${version.name}.war&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;warfile.path&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;${dist.dir}/${warfile}&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;war</span> <span style="color: #000066;">warfile</span>=<span style="color: #ff0000;">&quot;${warfile.path}&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        <span style="color: #808080; font-style: italic;">&lt;!-- add the rest of the war task specifics here --&gt;</span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/war<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/target<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;target</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;auto-build&quot;</span> <span style="color: #000066;">depends</span>=<span style="color: #ff0000;">&quot;checkbamboo,test,package,publish&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span></pre></div></div>

<p>So there are a few things going on here.<br />
First, we have a target called package that simply depends on a target called create-war.</p>
<p><span style="color: #808080;"><em>Although this isn&#8217;t really neccessary, it&#8217;s useful to have common target names across multiple projects. So if I had another project that creates a jar or a zip file, you would simply adjust the depends on the package target in that project. This way the lazy developers can always rely on running the package target regardless of what it actually spits out.</em></span></p>
<p>Next we have our create-war target.<br />
This target depends on a compile target (which aptly named, compiles our project) and the get-version target we defined previously.<br />
When it creates the war, it uses the ant project name and the version.name as the name of the war file. (real exciting, huh?)</p>
<p>Finally we have a target called auto-build.<br />
I include this target in any of my ant files that will be called from Bamboo. Again, this just makes it simpler to setup in bamboo since you don&#8217;t need to think about which target to run.<br />
This target can do anything you want it to and in my example I&#8217;ve included the bare minimum that I usually need a build to do&#8230;..</p>
<ul>
<li><strong>checkbamboo</strong> &#8211; this simply checks that ${user.name} is equal to the name of the user that bamboo runs as, and fails if it doesn&#8217;t.</li>
<li><strong>test</strong> &#8211; runs unit tests and generates reports</li>
<li><strong>package</strong> &#8211; runs our package target</li>
<li><strong>publish</strong> &#8211; publishes our artifact to our dependency management system (i.e. apache ivy, a maven repo, what have you)</li>
</ul>
<p>Some may wonder why the checkbamboo target exists and if it&#8217;s really useful. Although it&#8217;s very easy to get around, it&#8217;s there as a sanity check when developers are doing builds on their local machines and ensures that a developer does not accidentally publish a locally built artifact to the repository.</p>
<p>Obviously this is not a real and/or complete build file. It&#8217;s simply here to illustrate a basic outline of what&#8217;s needed for the automation to work.</p>
<h3>Got Versions?</h3>
<p>Our next order of business is to get versions setup in Jira.</p>
<p>There&#8217;s nothing special here&#8230;.  simply create a Jira Project, go into the manage versions screen and add the proper versions.<br />
Make sure all of the versions start out as Unreleased and are in the proper order. Bamboo will use the order provided by Jira to determine the latest version.</p>
<p>For our scenario, I&#8217;ve setup a Jira Project named &#8220;My Web App&#8221; with the key WEBMYAPP</p>
<p>My versions initially end up looking like this: (note: waiting to add the bugfix version till later)<br />
<img title="manage_versions" src="http://blog.sysbliss.com/wp-content/uploads/2008/08/manage_versions-300x159.png" alt="manage versions" /></p>
<h3>On To Bamboo</h3>
<p>The last part of the setup is to configure our project in Bamboo. I&#8217;ve already setup my project with the Project Info listed at the beginning of this post, and have tied it to version control (specifically subversion).</p>
<p>Now it&#8217;s time to start configuring the JiraVersions plugin. The first screen we need is in the Configuration &gt; Builder tab. Naviagte to there and click Edit Plan.</p>
<p>In the main Builder configuration, select Ant as your builder and put build.xml in the Build File box.<br />
Now in the Target box, let&#8217;s add our build target and pass the version properties our build is expecting:</p>
<p><strong> </strong></p>
<pre><strong>autobuild -Dversion.name=${bamboo.custom.jiraversion.name} -Dversion.released=${bamboo.custom.jiraversion.released} -Dversion.type=${bamboo.custom.jiraversion.type}</strong></pre>
<p><strong></strong></p>
<p>Our builder ends up looking something like:</p>
<div class="mceTemp">
<dl id="attachment_26" class="wp-caption alignnone" style="width: 310px;">
<dt class="wp-caption-dt"><a rel="lightbox" href="http://blog.sysbliss.com/wp-content/uploads/2008/08/builder_config.png"><img class="size-medium wp-image-26" title="builder_config" src="http://blog.sysbliss.com/wp-content/uploads/2008/08/builder_config-300x113.png" alt="builder configuration" width="300" height="113" /></a></dt>
</dl>
</div>
<p>Scrolling down on this same screen, click the &#8220;Enable Jira Versions&#8221; checkbox and the Jira Versions options will appear.</p>
<p><strong><span style="color: #000000;">General Settings<br />
</span></strong><span style="color: #000000;">First we need to let Bamboo know where to find our Jira Project by giving it the Jira Project key. You can click the test button to see if it Bamboo can find the project in the Jira server.</span></p>
<p>Next, set the Default Version Strategy to &#8220;Current Unreleased Version&#8221;. This tells Bamboo to ask Jira for the current unreleased version during &#8220;normal&#8221; operation. We&#8217;ll see how to override this later for a single build.</p>
<p>The Null Version strategy tells Bamboo what to do if Jira either has no versions setup, or none of the versions are unreleased (resulting in a null version returned).</p>
<p>The best idea is to set this value to &#8220;Skip and Pass Build&#8221; which will mark the build as successful but not actually build anything.</p>
<p><span style="color: #808080;"><em>note: if we set it to fail the build, then builds that are fully released will fail just because there are no open/unreleased versions which might cause unwanted results in your project dependency chain.</em></span></p>
<p>In the future, you&#8217;ll have even more options&#8230;. (<a href="http://developer.atlassian.com/jira/browse/BJVER-6" target="_blank">BJVER-6</a>).</p>
<p>Now we can setup our version appenders. These let you append any string on to the version name before it gets expanded by any other fields. In our scenario, we&#8217;re going to append the full Bamboo build key (including the number) to the end of unreleased version names.</p>
<p>To do this, set the Unreleased Appender field to: <strong>-${bamboo.buildResultKey}</strong><br />
We&#8217;ll just leave the released appender field blank.</p>
<p><a rel="lightbox" href="http://blog.sysbliss.com/wp-content/uploads/2008/08/jira_version_general_config.png"><img class="alignnone size-medium wp-image-29" title="jira_version_general_config" src="http://blog.sysbliss.com/wp-content/uploads/2008/08/jira_version_general_config-300x116.png" alt="" width="300" height="116" /></a></p>
<p><strong>Version Types</strong></p>
<p>The version types section allows you to add keywords that will be searched for in the version name and used as the type of release.<br />
The searching uses a similar algorithm as the php version_compare function.</p>
<p>In our scenario we just need to setup dev and rc keywords.</p>
<p><a rel="lightbox" href="http://blog.sysbliss.com/wp-content/uploads/2008/08/version_type_config.png"><img class="alignnone size-medium wp-image-32" title="version_type_config" src="http://blog.sysbliss.com/wp-content/uploads/2008/08/version_type_config-300x108.png" alt="" width="300" height="108" /></a></p>
<p>We&#8217;re now done configuring the Builder section, so we can click the save button at the bottom of the screen and move on to the Post Actions tab.</p>
<p><strong>Post Build Commands</strong></p>
<p>Uner the Post Build Commands in the Post Actions tab, we need to add a Success Command.</p>
<p>This will be the absolute path on the Bamboo server to the shell script that will be responsible for deploying our app to the various servers.</p>
<p>We will setup the script to accept the properties set by the JiraVersions plugin as well as the Bamboo build result key so we need to pass them to the script here.</p>
<p><strong> </strong></p>
<pre><strong>/opt/bamboo/deploy-scripts/deploy-webapp.sh -n ${bamboo.custom.jiraversion.name} -r ${bamboo.custom.jiraversion.released} -t ${bamboo.custom.jiraversion.type} -k ${bamboo.buildResultKey}</strong></pre>
<p><a rel="lightbox" href="http://blog.sysbliss.com/wp-content/uploads/2008/08/post_build_script.png"><img class="alignnone size-medium wp-image-34" title="post_build_script" src="http://blog.sysbliss.com/wp-content/uploads/2008/08/post_build_script-300x41.png" alt="" width="300" height="41" /></a></p>
<p><strong>Tagging</strong></p>
<p>Below the Post Build Commands, we can enable the Jira Versions Tagger which will allow us to make tags in our scm system based on some parameters.</p>
<p>In our scenario, we only want to tag successful builds, and since we&#8217;re using subversion, we&#8217;ll need to tell Bamboo where the tags should be made.<br />
<a rel="lightbox" href="http://blog.sysbliss.com/wp-content/uploads/2008/08/tag_success_builds.png"><img class="alignnone size-medium wp-image-40" title="tag_success_builds" src="http://blog.sysbliss.com/wp-content/uploads/2008/08/tag_success_builds-300x109.png" alt="" width="300" height="109" /></a></p>
<p>Finally, we only want Bamboo to tag Released versions of each version type.<br />
<a rel="lightbox" href="http://blog.sysbliss.com/wp-content/uploads/2008/08/tag_released_types.png"><img class="alignnone size-medium wp-image-42" title="tag_released_types" src="http://blog.sysbliss.com/wp-content/uploads/2008/08/tag_released_types-300x85.png" alt="" width="300" height="85" /></a></p>
<p>That&#8217;s it for the configuration. Just one more thing to do before we get to the workflow:</p>
<p><strong>Create the Deploy Script</strong></p>
<p>Our deploy script will be responsible for figuring out which environment(s) to deploy to based on the input parameters. The deploy worflow image at the beginning of this post shows what gets deployed to where.</p>
<p>Create a file in the same path as we defined in the post build command. In our case, we will create: <strong>/opt/bamboo/deploy-scripts/deploy-webapp.sh</strong></p>
<p>It should contain something similar to the following code:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/bash</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># parameter examples:</span>
<span style="color: #666666; font-style: italic;">#  -n 1.2.0-dev1</span>
<span style="color: #666666; font-style: italic;">#  -r false</span>
<span style="color: #666666; font-style: italic;">#  -t dev</span>
<span style="color: #666666; font-style: italic;">#  -k MY-WEBAPP-3</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">set</span> <span style="color: #660033;">-x</span>
&nbsp;
<span style="color: #007800;">version</span>=<span style="color: #ff0000;">&quot;&quot;</span>
<span style="color: #007800;">release</span>=<span style="color: #ff0000;">&quot;&quot;</span>
<span style="color: #007800;">version_type</span>=<span style="color: #ff0000;">&quot;&quot;</span>
<span style="color: #007800;">build_key</span>=<span style="color: #ff0000;">&quot;&quot;</span>
<span style="color: #007800;">release_env</span>=<span style="color: #ff0000;">&quot;&quot;</span>
&nbsp;
<span style="color: #007800;">mypath</span>=<span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">dirname</span> <span style="color: #ff0000;">&quot;$0&quot;</span><span style="color: #000000; font-weight: bold;">`</span>
&nbsp;
<span style="color: #007800;">DEV_ENV</span>=<span style="color: #ff0000;">&quot;dev.mydomain.com&quot;</span>
<span style="color: #007800;">QA_ENV</span>=<span style="color: #ff0000;">&quot;qa.mydomain.com&quot;</span>
<span style="color: #007800;">BUG_ENV</span>=<span style="color: #ff0000;">&quot;bugfix.mydomain.com&quot;</span>
<span style="color: #007800;">STAGE_ENV</span>=<span style="color: #ff0000;">&quot;staging.mydomain.com&quot;</span>
&nbsp;
<span style="color: #007800;">BAMBOO_HOME</span>=<span style="color: #ff0000;">&quot;/opt/bamboo/bamboo-home&quot;</span>
<span style="color: #007800;">dist_dir</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$BAMBOO_HOME</span>/xml-data/build-dir/WEB-MYAPP/dist&quot;</span>
&nbsp;
&nbsp;
<span style="color: #666666; font-style: italic;"># ~~~~~~~~~~~~~~~~</span>
<span style="color: #666666; font-style: italic;">#   Functions</span>
<span style="color: #666666; font-style: italic;">#     </span>
<span style="color: #666666; font-style: italic;"># ~~~~~~~~~~~~~~~~</span>
&nbsp;
usage<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #7a0874; font-weight: bold;">&#123;</span>
&nbsp;
   <span style="color: #c20cb9; font-weight: bold;">cat</span> <span style="color: #cc0000; font-style: italic;">&lt;&lt;EOF
    usage [-opts] deploy-webapp.sh
&nbsp;
     -n [version number] (might be blank) (ex. 1.0.1-dev1)
     -r [released] (ex. true|false )
     -t [version type] (might be blank) (ex. dev, rc, blank for prod)
     -k [build key] 
&nbsp;
EOF</span>
&nbsp;
<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
deploy <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#123;</span>
&nbsp;
   <span style="color: #000000; font-weight: bold;">set</span> <span style="color: #660033;">-x</span>
&nbsp;
   <span style="color: #007800;"><span style="color: #c20cb9; font-weight: bold;">env</span></span>=$<span style="color: #000000;">1</span>
&nbsp;
   <span style="color: #7a0874; font-weight: bold;">cd</span> <span style="color: #007800;">$dist_dir</span>
&nbsp;
   <span style="color: #007800;">box_list</span>=$<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">eval</span> <span style="color: #7a0874; font-weight: bold;">echo</span> \$<span style="color: #ff0000;">&quot;<span style="color: #007800;">${env}</span>_ENV&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
&nbsp;
   <span style="color: #000000; font-weight: bold;">for</span> i <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #007800;">$box_list</span>
   <span style="color: #000000; font-weight: bold;">do</span>
&nbsp;
    <span style="color: #666666; font-style: italic;"># Move new war file out and stop web services</span>
    <span style="color: #666666; font-style: italic;">#</span>
    <span style="color: #c20cb9; font-weight: bold;">scp</span> <span style="color: #007800;">$artifact_name</span> tomcat<span style="color: #000000; font-weight: bold;">@</span><span style="color: #800000;">${i}</span>:<span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>tmp<span style="color: #000000; font-weight: bold;">/</span>
    <span style="color: #c20cb9; font-weight: bold;">ssh</span> tomcat<span style="color: #000000; font-weight: bold;">@</span><span style="color: #800000;">${i}</span> <span style="color: #c20cb9; font-weight: bold;">sudo</span> monit stop tomcat_8080
    <span style="color: #c20cb9; font-weight: bold;">sleep</span> 5s
&nbsp;
    <span style="color: #666666; font-style: italic;"># Clean up any leftover Java processes (that were not killed by monit)</span>
    <span style="color: #666666; font-style: italic;"># Move the new war file into the proper place</span>
    <span style="color: #666666; font-style: italic;">#</span>
    <span style="color: #c20cb9; font-weight: bold;">ssh</span> tomcat<span style="color: #000000; font-weight: bold;">@</span><span style="color: #800000;">${i}</span> <span style="color: #c20cb9; font-weight: bold;">killall</span> <span style="color: #660033;">-u</span> tomcat java
    <span style="color: #c20cb9; font-weight: bold;">ssh</span> tomcat<span style="color: #000000; font-weight: bold;">@</span><span style="color: #800000;">${i}</span> <span style="color: #c20cb9; font-weight: bold;">mv</span> <span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>tmp<span style="color: #000000; font-weight: bold;">/</span><span style="color: #800000;">${artifact_name}</span> <span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>tomcat<span style="color: #000000; font-weight: bold;">/</span>apache-tomcat-6.0.16<span style="color: #000000; font-weight: bold;">/</span>webapps<span style="color: #000000; font-weight: bold;">/</span>my-webapp.war
    <span style="color: #c20cb9; font-weight: bold;">sleep</span> 5s
&nbsp;
    <span style="color: #666666; font-style: italic;"># Start up webapp</span>
    <span style="color: #666666; font-style: italic;">#</span>
    <span style="color: #c20cb9; font-weight: bold;">ssh</span> tomcat<span style="color: #000000; font-weight: bold;">@</span><span style="color: #800000;">${i}</span> <span style="color: #c20cb9; font-weight: bold;">sudo</span> monit start tomcat_8080
&nbsp;
   <span style="color: #000000; font-weight: bold;">done</span>
&nbsp;
<span style="color: #7a0874; font-weight: bold;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># ~~~~~~~~~~~~~~~~</span>
<span style="color: #666666; font-style: italic;">#   Main</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;"># ~~~~~~~~~~~~~~~~</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Get arguments (passed in from bamboo)</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #007800;">$#</span> <span style="color: #660033;">-ge</span> <span style="color: #000000;">1</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">while</span> <span style="color: #7a0874; font-weight: bold;">getopts</span> :r:n:t:k: zz; <span style="color: #000000; font-weight: bold;">do</span>
        <span style="color: #000000; font-weight: bold;">case</span> <span style="color: #007800;">$zz</span> <span style="color: #000000; font-weight: bold;">in</span>
        n<span style="color: #7a0874; font-weight: bold;">&#41;</span>   <span style="color: #007800;">version</span>=$<span style="color: #000000;">2</span> <span style="color: #000000; font-weight: bold;">;;</span>
        r<span style="color: #7a0874; font-weight: bold;">&#41;</span>   <span style="color: #007800;">release</span>=$<span style="color: #000000;">4</span>   <span style="color: #000000; font-weight: bold;">;;</span>
        t<span style="color: #7a0874; font-weight: bold;">&#41;</span>   <span style="color: #007800;">version_type</span>=$<span style="color: #000000;">6</span>  <span style="color: #000000; font-weight: bold;">;;</span>
        k<span style="color: #7a0874; font-weight: bold;">&#41;</span>   <span style="color: #007800;">build_key</span>=$<span style="color: #000000;">8</span> <span style="color: #000000; font-weight: bold;">;;</span>
&nbsp;
        <span style="color: #000000; font-weight: bold;">*</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>   usage; <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">2</span> <span style="color: #000000; font-weight: bold;">;;</span>
        <span style="color: #000000; font-weight: bold;">esac</span>
    <span style="color: #000000; font-weight: bold;">done</span>
    <span style="color: #7a0874; font-weight: bold;">shift</span> <span style="color: #000000; font-weight: bold;">`</span><span style="color: #c20cb9; font-weight: bold;">expr</span> <span style="color: #007800;">$OPTIND</span> - <span style="color: #000000;">1</span> <span style="color: #000000; font-weight: bold;">`</span>
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># If no version number, just exit</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #800000;">${#version}</span> <span style="color: #660033;">-eq</span> <span style="color: #000000;">0</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
&nbsp;
   <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">&quot;(<span style="color: #780078;">`date`</span>) ERROR - no version number - exiting...&quot;</span>
   <span style="color: #7a0874; font-weight: bold;">exit</span> <span style="color: #000000;">1</span>
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Check if this is a release or not</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">${release}</span>&quot;</span> == <span style="color: #ff0000;">&quot;true&quot;</span> <span style="color: #7a0874; font-weight: bold;">&#93;</span>; <span style="color: #000000; font-weight: bold;">then</span>
&nbsp;
     <span style="color: #007800;">artifact_name</span>=<span style="color: #ff0000;">&quot;my-webapp-<span style="color: #007800;">${version}</span>.war&quot;</span>
&nbsp;
     <span style="color: #000000; font-weight: bold;">case</span> <span style="color: #007800;">$version_type</span> <span style="color: #000000; font-weight: bold;">in</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">#released non-production versions go to DEV and QA</span>
        dev<span style="color: #000000; font-weight: bold;">|</span>rc<span style="color: #7a0874; font-weight: bold;">&#41;</span>
              <span style="color: #007800;">release_env</span>=<span style="color: #ff0000;">&quot;DEV,QA&quot;</span>
              <span style="color: #000000; font-weight: bold;">;;</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">#released production versions go to STAGE</span>
        <span style="color: #000000; font-weight: bold;">*</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
            <span style="color: #007800;">release_env</span>=<span style="color: #ff0000;">&quot;STAGE&quot;</span>
              <span style="color: #000000; font-weight: bold;">;;</span>
     <span style="color: #000000; font-weight: bold;">esac</span>
<span style="color: #000000; font-weight: bold;">else</span>
     <span style="color: #000000; font-weight: bold;">case</span> <span style="color: #007800;">$version_type</span> <span style="color: #000000; font-weight: bold;">in</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">#Un-Released non-production versions go to DEV</span>
        dev<span style="color: #000000; font-weight: bold;">|</span>rc<span style="color: #7a0874; font-weight: bold;">&#41;</span>
            <span style="color: #007800;">release_env</span>=<span style="color: #ff0000;">&quot;DEV&quot;</span>
            <span style="color: #000000; font-weight: bold;">;;</span>
&nbsp;
        <span style="color: #666666; font-style: italic;">#UN-Released production versions go to BUGFIX</span>
        <span style="color: #000000; font-weight: bold;">*</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
            <span style="color: #007800;">release_env</span>=<span style="color: #ff0000;">&quot;BUG&quot;</span>
            <span style="color: #000000; font-weight: bold;">;;</span>
     <span style="color: #000000; font-weight: bold;">esac</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">fi</span>
&nbsp;
<span style="color: #666666; font-style: italic;"># Release code to requested environments</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #000000; font-weight: bold;">for</span> i <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #007800;">$release_env</span>
<span style="color: #000000; font-weight: bold;">do</span>
    <span style="color: #7a0874; font-weight: bold;">echo</span> <span style="color: #660033;">-e</span> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\t</span><span style="color: #000099; font-weight: bold;">\t</span>(<span style="color: #780078;">`date`</span>) Releasing to <span style="color: #007800;">$i</span>&quot;</span>
    deploy <span style="color: #007800;">$i</span>
<span style="color: #000000; font-weight: bold;">done</span></pre></div></div>

<h2>Go With The Flow</h2>
<p>Now that everything is setup, we&#8217;re ready to go through the basic development cycle workflow.</p>
<p>This is pretty straight forward with only a few things to watch out for&#8230;..</p>
<p>So let&#8217;s get started. Per our versions, we&#8217;re starting with iteration 1 of our webapp project.</p>
<p>Generally, we will be adding new features in our iterations based on User Stories that are entered into Jira.</p>
<p>As we close out Jira issues and commit code, Bamboo will build our unreleased dev1 version for us.</p>
<p>We can check the status of all version builds by going to the Jira Versions tab for our build plan. After the first checkin, the Jira Versions will look somethin like the following:<br />
<a rel="lightbox" href="http://blog.sysbliss.com/wp-content/uploads/2008/08/jv_ur_dev1.png"><img class="alignnone size-medium wp-image-47" title="jv_ur_dev1" src="http://blog.sysbliss.com/wp-content/uploads/2008/08/jv_ur_dev1-300x227.png" alt="" width="300" height="227" /></a></p>
<p>After our iteration is finished, it&#8217;s time to release dev1. This is a 2 step process.</p>
<p>First, go into the manage versions screen in Jira and click the release link next to the 1.0.0-dev1 version.</p>
<p>Second, go to the Jira Versions tab in Bamboo. We will now see the released dev1 version with a link that will let us do a manual build.</p>
<p>We need to kick off the build manually because Bamboo is now going to be building the un-released dev2 version when code commits happen. Thus,<strong> it is important to do this manual build as soon as you release the version in Jira to make sure that no commits happen after the release</strong>.</p>
<p><a rel="lightbox" href="http://blog.sysbliss.com/wp-content/uploads/2008/08/jv_r_dev1.png"><img class="alignnone size-medium wp-image-48" title="jv_r_dev1" src="http://blog.sysbliss.com/wp-content/uploads/2008/08/jv_r_dev1-300x58.png" alt="" width="300" height="58" /></a></p>
<p>At this point, we just follow this same process for all of our iterations. When we are ready to release the final iteration version, we need to do one extra step: merge the dev versions into the first release candidate.</p>
<p>Merging will do a couple of things for us. It will allow users to see everything that has been included in the release candidate. It will also remove the merged version from the Jira Versions tab in Bamboo.  This makes it impossible for someone to accidentally re-build an already released dev version.</p>
<p>You can still get to the old builds by going to the Completed Builds tab in bamboo.</p>
<p>To merge, you simply use the merge links in the Manage Versions section of Jira.</p>
<p>Once our iterations are complete and we move on to the first release candidate, the workflow remains the same&#8230; commit, Babmoo builds, release when ready.</p>
<p>When we reach the point of releasing the final release candidate, we again need to merge. This time we will merge all of the rc versions into the production version. From here, we just go along the workflow as normal and release the production version when ready.</p>
<p>Throughout the development cycles, you shee see the following:</p>
<ul>
<li>Builds appearing in the Jira Versions tab</li>
<li>Un-released versions being deployed to the development server.</li>
<li>Released versions being deployed to the development and QA servers</li>
<li>Released versions being tagged in subversion</li>
<li>Un-released Production builds being deployed to the bugfix server</li>
<li>Released Production build deployed to the staging server.</li>
</ul>
<p>If everything is good to go on the staging server, we can then manually deploy it to the actual production server. This is left as a manual process just to ensure that a human is watching the process and making sure it goes ok.</p>
<p>Finally, if there are emergency bugs that need to be fixed in production without a full development cycle, we can simply add a new version in Jira called 1.0.1</p>
<p>From there, we just do the normal process of committing code, releasing when ready, manually building the released version and manually deploying from staging to production.</p>
<p>And there you have it. However, there&#8217;s more&#8230;&#8230;</p>
<p><span style="color: #ff0000;"><strong>Beware of Null Versions<br />
</strong><span style="color: #000000;">We have our build set to pass with success if there are no versions returned from Jira. This is useful for dependency builds that need to complete within a larger build tree, however, this means a new development rule must be followed:</span></span></p>
<p><span style="color: #ff0000;"><span style="color: #000000;"> <strong>No code should be committed to a project without an unreleased version.</strong></span></span></p>
<p>If code is committed, bamboo will see the change in the scm and try to run a build, but since no version will be returned by Jira, it will simply do nothing but look successful.  This is not the optimal scenario and <a href="http://developer.atlassian.com/jira/browse/BJVER-6" target="_blank">BJVER-6</a> aims to make this a little more fool proof.</p>
<p>It&#8217;s also a good idea to create a subversion commit hook that checks Jira for an unreleased version and fails the commit if it doesn&#8217;t find one.</p>
<p><span style="color: #808080;"><em>I will post a link to the subversion pre-commit hook once I get it finished.</em></span></p>
<p>I hope this post was helpful.</p>
<img src="http://feeds.feedburner.com/~r/sysblissblog/~4/QeKYicQgu1g" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.sysbliss.com/uncategorized/release-management-with-atlassian-bamboo-and-jira.html/feed</wfw:commentRss>
		<slash:comments>54</slash:comments>
		<feedburner:origLink>http://blog.sysbliss.com/uncategorized/release-management-with-atlassian-bamboo-and-jira.html</feedburner:origLink></item>
		<item>
		<title>Sysbliss wins Atlassian Codegeist for Bamboo</title>
		<link>http://feedproxy.google.com/~r/sysblissblog/~3/ML4vFloeX6E/sysbliss-wins-atlassian-codegeist-for-bamboo.html</link>
		<comments>http://blog.sysbliss.com/uncategorized/sysbliss-wins-atlassian-codegeist-for-bamboo.html#comments</comments>
		<pubDate>Fri, 20 Jun 2008 14:16:55 +0000</pubDate>
		<dc:creator>jdoklovic</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.sysbliss.com/?p=7</guid>
		<description><![CDATA[My Pre/Post Build Command plugin won the Atlassian Codegeist III Contest.
From the announcement:
This is terrific plugin that enables all sorts of new possibilities for Bamboo. It&#8217;s one of those gateway plugins that opens up a whole new category of customizations.
The full announcement can be viewed on the Atlassian Blog
]]></description>
			<content:encoded><![CDATA[<p>My Pre/Post Build Command plugin won the Atlassian Codegeist III Contest.</p>
<p>From the announcement:<br />
<cite class="shutter" dir="ltr">This is terrific plugin that enables all sorts of new possibilities for Bamboo. It&#8217;s one of those gateway plugins that opens up a whole new category of customizations.</cite></p>
<p>The full announcement can be <a href="http://blogs.atlassian.com/developer/2008/06/finally_the_results_of_codegei.html">viewed on the Atlassian Blog</a></p>
<img src="http://feeds.feedburner.com/~r/sysblissblog/~4/ML4vFloeX6E" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.sysbliss.com/uncategorized/sysbliss-wins-atlassian-codegeist-for-bamboo.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.sysbliss.com/uncategorized/sysbliss-wins-atlassian-codegeist-for-bamboo.html</feedburner:origLink></item>
		<item>
		<title>Managing Dovecot Sieve scripts with Horde-Ingo</title>
		<link>http://feedproxy.google.com/~r/sysblissblog/~3/kPAi2EvlLGs/managing-dovecot-sieve-scripts-with-horde-ingo.html</link>
		<comments>http://blog.sysbliss.com/linux/managing-dovecot-sieve-scripts-with-horde-ingo.html#comments</comments>
		<pubDate>Thu, 19 Jun 2008 20:14:45 +0000</pubDate>
		<dc:creator>jdoklovic</dc:creator>
				<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://blog.sysbliss.com/?p=6</guid>
		<description><![CDATA[I finally got around to getting sieve working with dovecot which was pretty easy. Next, I wanted to be able to manage the sieve rules via the Horde-Ingo webmail interface. This seemed like it should be an easy and common thing to do, however, it ended up taking a couple of days to sift through [...]]]></description>
			<content:encoded><![CDATA[<p>I finally got around to getting sieve working with dovecot which was pretty easy. Next, I wanted to be able to manage the sieve rules via the Horde-Ingo webmail interface. This seemed like it should be an easy and common thing to do, however, it ended up taking a couple of days to sift through the rather poor hored/ingo docs, email back and forth on the mailing list, and do a lot of trial and error. (mostly error).</p>
<p>Finally, I found a solution that works&#8230;.  here it is (Assuming you already have dovecot-sieve working):</p>
<h3>Software:</h3>
<p>Debian etch<br />
Dovecot 1.0.13 (with dovecot common)<br />
Horde 3.2-RC2<br />
Ingo 1.2-RC2</p>
<h3>Step 1: Setup proper permissions</h3>
<p>For Ingo to be able to write out sieve scripts, the apache user needs permissions to write to the Maildir folders.<br />
I did this by simply adding the www-data user to the vmail group.</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">:<span style="color: #666666; font-style: italic;"># adduser www-data vmail</span>
:<span style="color: #666666; font-style: italic;"># /etc/init.d/apache2 restart</span></pre></div></div>

<p>This will give www-data permissions to write to the Maildir folders (owned by vmail:vmail) but if we just let Ingo create the scripts from scratch, they will be owned by www-data:www-data and vmail won&#8217;t be able to use them.</p>
<p>To correct this, just make sure you create an empty .dovecot.sieve when the user&#8217;s Maildir folder is created.</p>
<p>I handled this by adding:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">touch</span> $<span style="color: #000000;">2</span><span style="color: #000000; font-weight: bold;">/</span>Maildir<span style="color: #000000; font-weight: bold;">/</span>.dovecot.sieve</pre></div></div>

<p>to my /usr/bin/maildirmake script.</p>
<h3>Step 2: Setup Ingo Backend</h3>
<p>In the horde/ingo/config directory, there is a file called backends.php. This file by default contains a bunch of different entries that tell Ingo how to store the mail filters.</p>
<p>For Ingo to actually work, there should only be one entry in this file (as I&#8217;m told). So for starters, just delete all of the entries in this file.</p>
<p>Now that we have a clean backends.php, we need to add an entry to tell Ingo where and how to save our .dovecot.sieve scripts.</p>
<p>There are many options for storage but the simplest for our purposes is to just use the filesystem.<br />
To enable this, add the following entry to the file</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$backends</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'dovecot'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
    <span style="color: #0000ff;">'driver'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'vfs'</span><span style="color: #339933;">,</span>
    <span style="color: #0000ff;">'hordeauth'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">,</span>
    <span style="color: #0000ff;">'params'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
        <span style="color: #0000ff;">'filename'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'.dovecot.sieve'</span><span style="color: #339933;">,</span>
        <span style="color: #0000ff;">'vfsroot'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'/var/vmail'</span><span style="color: #339933;">,</span>
        <span style="color: #0000ff;">'vfs_path'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'/example.com/%u/Maildir'</span><span style="color: #339933;">,</span>
        <span style="color: #0000ff;">'vfstype'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'file'</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
    <span style="color: #0000ff;">'script'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #0000ff;">'sieve'</span><span style="color: #339933;">,</span>
    <span style="color: #0000ff;">'scriptparams'</span> <span style="color: #339933;">=&amp;</span>gt<span style="color: #339933;">;</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span>
<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>This should all be pretty self-explanatory, but you&#8217;ll notice on line 7, we&#8217;re hardcoding the domain. This is because Ingo will expand %u as the user, but it does not currently expand any variable as the domain. (i.e. %d)</p>
<p><a title="domain workaround" href="http://blog.sysbliss.com/linux/managing-dovecot-sieve-scripts-with-horde-ingo.html#comment-161">See Domain Workaround Below</a></p>
<p>That&#8217;s it. If you now log into horde and create/edit filters, they should be saved to the .dovecot.sieve file in the user&#8217;s Maildir.  Pretty simple, and now documented.  <img src='http://blog.sysbliss.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Enjoy.</p>
<img src="http://feeds.feedburner.com/~r/sysblissblog/~4/kPAi2EvlLGs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.sysbliss.com/linux/managing-dovecot-sieve-scripts-with-horde-ingo.html/feed</wfw:commentRss>
		<slash:comments>14</slash:comments>
		<feedburner:origLink>http://blog.sysbliss.com/linux/managing-dovecot-sieve-scripts-with-horde-ingo.html</feedburner:origLink></item>
		<item>
		<title>Bamboo 2.0 Pre/Post Command Plugin</title>
		<link>http://feedproxy.google.com/~r/sysblissblog/~3/KhBCaKbVRTI/bamboo-20-prepost-command-plugin.html</link>
		<comments>http://blog.sysbliss.com/uncategorized/bamboo-20-prepost-command-plugin.html#comments</comments>
		<pubDate>Fri, 09 May 2008 14:42:40 +0000</pubDate>
		<dc:creator>jdoklovic</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.sysbliss.com/?p=5</guid>
		<description><![CDATA[A new version of the Bamboo command runner plugin is available:
http://confluence.atlassian.com/display/BAMEXT/Pre-Post+Build+Command+Plugin
The bamboo 1.2.4 version was updated so PRE-build commands can now be specified.

A new 2.0 version was created as well.
]]></description>
			<content:encoded><![CDATA[<p>A new version of the Bamboo command runner plugin is available:<br />
<a href="http://confluence.atlassian.com/display/BAMEXT/Pre-Post+Build+Command+Plugin">http://confluence.atlassian.com/display/BAMEXT/Pre-Post+Build+Command+Plugin</a></p>
<p>The bamboo 1.2.4 version was updated so PRE-build commands can now be specified.<br />
<br />
A new 2.0 version was created as well.</p>
<img src="http://feeds.feedburner.com/~r/sysblissblog/~4/KhBCaKbVRTI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.sysbliss.com/uncategorized/bamboo-20-prepost-command-plugin.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.sysbliss.com/uncategorized/bamboo-20-prepost-command-plugin.html</feedburner:origLink></item>
		<item>
		<title>Atlassian Bamboo Post Build Command Runner Plugin</title>
		<link>http://feedproxy.google.com/~r/sysblissblog/~3/cBlGako-2Oc/atlassian-bamboo-post-build-command-runner-plugin.html</link>
		<comments>http://blog.sysbliss.com/general-dev/atlassian-bamboo-post-build-command-runner-plugin.html#comments</comments>
		<pubDate>Fri, 28 Mar 2008 17:30:00 +0000</pubDate>
		<dc:creator>jdoklovic</dc:creator>
				<category><![CDATA[General Development]]></category>

		<guid isPermaLink="false">http://blog.sysbliss.com/?p=4</guid>
		<description><![CDATA[Overview
We use Atlassian Bamboo as our continuous build server and for a while I&#8217;ve wanted to kick off arbitrary command line commands after a build is completed.  Apparently some other developers have been asking for this as well: BAM-679.
In response, I&#8217;ve written this plugin that can run an arbitrary command when a build passes [...]]]></description>
			<content:encoded><![CDATA[<h2>Overview</h2>
<p>We use <a href="http://www.atlassian.com/software/bamboo/">Atlassian Bamboo</a> as our continuous build server and for a while I&#8217;ve wanted to kick off arbitrary command line commands after a build is completed.  Apparently some other developers have been asking for this as well: <a href="http://jira.atlassian.com/browse/BAM-679">BAM-679.</a></p>
<p>In response, I&#8217;ve written this plugin that can run an arbitrary command when a build passes or fails. The pass and fail commands are specified on the Post Actions configuration page.</p>
<p>The plugin is now hosted on the Atlassian Developer Network.<br />
Please <a href="http://confluence.atlassian.com/display/BAMEXT/Pre-Post+Build+Command+Plugin">visit the plugin homepage</a>.</p>
<img src="http://feeds.feedburner.com/~r/sysblissblog/~4/cBlGako-2Oc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blog.sysbliss.com/general-dev/atlassian-bamboo-post-build-command-runner-plugin.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blog.sysbliss.com/general-dev/atlassian-bamboo-post-build-command-runner-plugin.html</feedburner:origLink></item>
	</channel>
</rss><!-- Dynamic Page Served (once) in 3.382 seconds -->
