Skip to content
Skip to breadcrumbs
Skip to header menu
Skip to action menu
Skip to quick search
Quick Search
Browse
Pages
Blog
Labels
Attachments
Mail
Advanced
What’s New
Space Directory
Feed Builder
Keyboard Shortcuts
Confluence Gadgets
Log In
Dashboard
Groovy
Copy Page
You are not logged in. Any changes you make will be marked as
anonymous
. You may want to
Log In
if you already have an account. You can also
Sign Up
for a new account.
This page is being edited by
.
Paragraph
Paragraph
Heading 1
Heading 2
Heading 3
Heading 4
Heading 5
Heading 6
Preformatted
Quote
Bold
Italic
Underline
More colours
Strikethrough
Subscript
Superscript
Monospace
Clear Formatting
Bullet list
Numbered list
Outdent
Indent
Align left
Align center
Align right
Link
Table
Insert
Insert Content
Image
Link
Attachment
Symbol
Emoticon
Wiki Markup
Horizontal rule
tinymce.confluence.insert_menu.macro_desc
Info
JIRA Issue
Status
Gallery
Tasklist
Table of Contents
Other Macros
Page Layout
No Layout
Two column (simple)
Two column (simple, left sidebar)
Two column (simple, right sidebar)
Three column (simple)
Two column
Two column (left sidebar)
Two column (right sidebar)
Three column
Three column (left and right sidebars)
Undo
Redo
Find/Replace
Keyboard Shortcuts Help
<p><a href="http://boostalicious.org">Boost</a> is a framework for working with Java. This page describes how to use the IoC part of Boost called <a href="http://boostalicious.org/learn/spider-101">Spider</a> with Groovy.</p> <p>Spider has a very interface oriented view of the world. If you are into <em>Interface oriented design</em> (e.g. Ken Pugh's book) and use fine-grained interfaces, you will feel right at home. So first, let's create a Java interface:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> // Java package foo; public interface MeTwo { void reportStuff(); } </pre></td></tr></table> <p>and a corresponding implementation:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> // Java package foo; public class DefaultMeTwo implements MeTwo { public void reportStuff() { System.out.println("Reporting stuff"); } } </pre></td></tr></table> <p>We could have just as easily used Groovy. As an example, here's another interface (this time Groovy):</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> package foo interface IGetInjected { void doStuff() } </pre></td></tr></table> <p>And its Groovy implementation:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> package foo class DefaultIGetInjected implements IGetInjected { void doStuff() { println("Doing stuff") } } </pre></td></tr></table> <p>Now, let's create a class that uses these implementations.</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> package foo import au.net.netstorm.boost.spider.api.entry.Go @PackageScope class PleaseDontGo implements Go { IGetInjected yippee MeTwo rippa void go(String[] args) { yippee.doStuff() rippa.reportStuff() } } </pre></td></tr></table> <p>The <code>go()</code> method is the Spider's answer to Java's <code>main()</code> method, i.e. it is the entry point for IoC managed webs of classes. Also, <code>@PackageScope</code> is an AST macro. The Spider does field injection based on package scoped fields. However, Groovy normally turns packages scoped fields into properties and we don't want that here. The AST macro tells the Groovy compiler to leave the fields in the <code>PleaseDontGo</code> class alone and not try to turn them into properties. We could have placed the annotation individually on fields if we preferred. Placing it at the class level makes it apply to all package scoped fields.</p> <p>Now, let's bootstrap the IoC container so that we can run our application:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> package foo import au.net.netstorm.boost.spider.ioc.BoostWeb import au.net.netstorm.boost.spider.api.entry.SpiderMain def main = new SpiderMain(BoostWeb) main.main(PleaseDontGo) </pre></td></tr></table> <p>Here, <code>BoostWeb</code> provides some nice defaults for us to use. Running this gives:</p> <table class="wysiwyg-macro" data-macro-name="noformat" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e25vZm9ybWF0fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> Doing stuff Reporting stuff </pre></td></tr></table> <p>We can also override the Web. For instance, we can supply our own web:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> package foo import au.net.netstorm.boost.spider.api.config.web.Web import au.net.netstorm.boost.spider.api.config.wire.Wire class TangledWeb implements Web { @PackageScope Wire wire void web() { wire.ref({ println 'Reporting stuff2' } as MeTwo).to(MeTwo) } } </pre></td></tr></table> <p>Which tells the IoC framework to use the supplied closure whenever it needs to inject a <code>MeTwo</code> implementation. Note again the use of the PackageScope AST macro to override Groovy's default property behavior. With this in place, our main script becomes:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> def main = new SpiderMain(BoostWeb, TangledWeb) main.main(PleaseDontGo) </pre></td></tr></table> <p>And the output will be:</p> <table class="wysiwyg-macro" data-macro-name="noformat" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e25vZm9ybWF0fQ&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> Doing stuff Reporting stuff2 </pre></td></tr></table> <p>You can also use Boost's <a href="http://boostalicious.org/learn/sniper-101/">testing facilities</a>. An example (<code>Foo</code> and <code>Person</code> classes not shown) to give you a flavor of these kinds of tests:</p> <table class="wysiwyg-macro" data-macro-name="code" style="background-image: url(/plugins/servlet/confluence/placeholder/macro-heading?definition=e2NvZGV9&locale=en_GB&version=2); background-repeat: no-repeat;" data-macro-body-type="PLAIN_TEXT"><tr><td class="wysiwyg-macro-body"><pre> @PackageScope class StringJoinerTest extends GroovyLifecycleTestCase implements HasFixtures, InjectableSubject, InjectableTest, LazyFields { StringJoiner subject private Person pa, pb Foo fooA, fooB Foo foo1Mock, foo2Mock void fixtures() { pa = new Person(first:'f1', last:'l1') pb = new Person(first:'f2', last:'l2') } void testLookup() { expect.oneCall(foo1Mock, "FOO", "toUpperCase") expect.oneCall(foo2Mock, "BAR", "toUpperCase") assert subject.join(pa.first, pb.last) == "f1l2" assert subject.join(fooA.bar, fooB.bar) == "barbar" assert subject.joinUpper(foo1Mock, foo2Mock) == "FOOBAR" } } </pre></td></tr></table> <p>Here, <code>fooA</code>, <code>fooB</code> and <code>subject</code> will be auto created with default values, <code>foo1Mock</code> and <code>foo2Mock</code> will be auto created as mocks, <code>pa</code> and <code>pb</code> are set using the <code>fixtures()</code> method. <code>GroovyLifecycleTestCase</code> is a slight variation of <code>LifecycleTestCase</code> which is built-in to Boost. The built-in one is a little too opinionated about the methods Groovy adds under the covers to its classes. The result is very compact test code albeit looking a little magical until you get used to this style of testing.</p>
Please type the word appearing in the picture.
Attachments
Labels
Location
Watch this page
< Edit
Preview >
Loading…
Save
Cancel
Next hint
search
attachments
weblink
advanced