The Kaptain on … stuff

27 Jan, 2010

Thanks for the shirt Atlassian!

Posted by: TheKaptain In: Development

So my t-shirt arrived today in the mail compliments of Atlassian. Bright green and well earned when I slayed the dragon, I’ll wear it with pride.  So far I’ve been getting the most mileage out of Bamboo and Jira, but I’ve also been tweaking Confluence to make it just right. Following right along with Atlassian’s lead, both TaskDock and Gliffy are offering $10 donation licenses for less than ten user systems, so I’ve pretty much got to at least try them out right?

Actually I’ve used Gliffy in Confluence before, and it’s come in handy more than once or twice. But between Balsamiq and OmniGraffle I’m already well equipped to cover up the fact that my artistic abilities lie somewhere below drawing stick men. TaskDock has however been installed and set up to nag me via email when I am getting behind schedule. Next will be Customware’s scaffolding and reporting plugins. The scaffolding capabilities make dealing with tables in Confluence a breeze – almost(but not quite) enough to make me abandon the wiki editor completely. Why take my word for it when you can just watch the video?

Anyhow, so far I’m very happy with the software and how it’s already helped me organize projects at home better. The t-shirt is just a nice bonus.

Here's the t-shirt
Reblog this post [with Zemanta]

Post to Twitter Tweet This Post

07 Jan, 2010

Bamboo, Grails and Git for Continuous Integration

Posted by: TheKaptain In: Development

Following up on my recent installation of the Atlassian product suite at home, I had a really positive experience setting up Bamboo to work with several of my recent Grails projects. Bamboo has proven to be a powerful and essential tool at my day job and I’ve really been looking forward to putting it to work for my personal projects. I’ve also been using Git for a repository lately, and while I have nothing but praise for my good friend svn, I have to say the ability to set up a new repository in 2 seconds flat is pretty damn convenient.

Since neither Grails nor Git are by default supported by Bamboo, I grabbed a couple of plugins to enable my home continuous integration system. Bamboo has a very sensible plugin model that allows for adding new capabilites with only a jar file in the right place and a server restart, and a fairly rich library of plugins. It’s also encouraging to see a company that is committed to eating their own dog food – recently they’ve moved their plugin resources to Jira studio as you can see on the Grails plugin home page. This gives you as the consumer of the software access to the wiki’d documentation, any open issues, and even visibility into when source code changes are committed. I’m assuming that last is subject to whether or not the plugin source code is open source or not, but still – pretty nifty.

The Grails plugin instructions speak for themselves in the 3 screen-shots on the one and only wiki page. Anything else you need to know is summarized in a one liner on the “Builder” tab when you select the Grails builder: “Use a new line to seperate Grails commands.” Gotta love clear, simple instructions. Drop the plugin jar into $BAMBOO_INSTALL_DIR/webapp/WEB-INF/lib, restart Bamboo and configure a new builder for Grails. Took a couple of minutes and knowing where my Grails install was located.

Adding the builder definition to Bamboo

A quick Google for “Bamboo git plugin” led to a bit of a hypertext chase that eventually ended up here. Looks like this particular plugin has passed through the hands of at least a couple of maintainers, but so far it’s worked exactly as advertised. And again, loving the dog food analogy, it’s nice to see a project enabling Git hosted on github. Thanks very much to Kristian Rosenvold for running with the ball on this one! Again, drop the jar into $BAMBOO_INSTALL_DIR/webapp/WEB-INF/lib and restart Bamboo. When creating a plan you will now have Git as a choice for a Source Repository. In my case I’m just using a plain file repository that resides on the build box, but it should work just as well with a remote repository.

Select Git as the source repository for a Bamboo plan

Setting up the Grails targets is similarly straightforward. Thanks to this article, which describes the Grails setup on Hudson, and reminded me about the –non-interactive flag since obviously the build server isn’t going to be able to interact with the console. I’m also using a couple of Grails plugins to provide static source code analysis so my parameters also include -coverage and a call to the codenarc script.

Select Grails as a builder and specifying which scripts to call for a Bamboo plan

I had a little trepidation about how this would all turn out after reading this blog post, but I’ve had much better results so far in my personal experience. It’s entirely possible that the key differentiator is wrapping Grails with Maven. It’s definitely not perfect, but it is getting better all the time. Hopefully you have better luck in the future Neil!

Reblog this post [with Zemanta]

Post to Twitter Tweet This Post

02 Jan, 2010

Atlassian: Here Be Dragons

Posted by: TheKaptain In: Cool Toys| Development

I’ve been using Atlassian tools at work for a few years now, and it’s hard to imagine how much different developing software would be without them. For those of you who aren’t familiar with Atlassian, here’s the 10,000 foot view.

The Atlassian Toolbox

Jira is the cornerstone of the stack and, with the addition of the ‘Agile’ GreenHopper plugin, is an ideal tool for tying together issue tracking and project planning in one easy to work with bundle. Crucible and Fisheye provide peer review and repository browsing. The Confluence wiki provides a great framework for organizing and sharing knowledge. Bamboo is an extremely versatile continuous integration platform. Crowd provides SSO and identity management. And they all can link together nicely to provide consolidated views spanning the entire stack.

Here Be Dragons

Late in 2009 Atlassian started a new marketing campaign geared towards smaller deployments: $60 to purchase 10 user licenses for the entire software stack, including 30 day trial licenses with support. Previously some of the applications were available for personal use(2 or 3 Users only) at no cost, and indeed I have a Confluence install I’ve been using for the last year, but this deal makes the entire stack available at what is really a very reasonable price. And they even include a fun, if slightly corny, tutorial which guides you through installing and configuring all of the applications to link them together. So here’s my experience ‘Slaying the Dragon’.

dragon_badge04

The very first thing I discovered was that my years old Intel iMac with 1GB of memory just wasn’t going to cut it. The recommendation is for 2GB of memory and “No other applications running — just the operating system, JAVA, PostgreSQL and the Atlassian applications” so I of course took that as an opportunity to ask Santa for a memory upgrade.

Ten days later, with 4GB of brand new RAM installed I got much further than the SLOW grind that was Crowd + Jira + Confluence + iTunes fighting with each other over 1 gig of memory(shudder). Aside from a couple of minor hiccups, everything installed without hassle and the instructions were nothing short of spectacular. I did have to make some tweaks to the postgres database configuration upping the number of allowed connections; apparently this setup is more than a little connection hungry, tsk tsk. Crowd is the one application I’m least familiar with, and integrating with it seemed to be the most actual ‘work’ but hey – if manually copying around and modifying a couple of configuration files is the biggest hassle involved in providing SSO for 5 enterprise apps, I think I can live with it.  I am probably going to have to bite the bullet and invest in a more practical server machine, but I’m pretty sure the 2010 budget can find room for at least one new computer.

Been There, Done That, Where’s my T-shirt?

I’ve already started to plan out milestones for the new year’s projects in Jira, so I guess I’m already committed to paying the $60 when my trial period expires. Especially when Atlassian is donating all proceeds to Room to Read. I get enterprise-ready software for cheap AND all the money goes to a good cause. Win-win in my books – and a great job by Atlassian(on both the software and the charitable good.) Did I mention they’re sending out free t-shirts to anyone who completes the challenge?
:)

In the gallery below is a screen shot for the single Jira Dashboard view you end up with at the end of the exercise. It ties together activity from each of the applications into one homogeneous view, and each widget is color coded to represent where the data is being drawn from. If you’re looking for an affordable solution to help streamline your work at home or in a small development team, check it out!

Reblog this post [with Zemanta]

Post to Twitter Tweet This Post

16 Dec, 2009

Jira Grails Plugin

Posted by: TheKaptain In: Development

I set out to explore some of the Atlassian API’s this week, along with a test drive of Jira 4, and ended up developing a simple XML-RPC plugin for Grails. Utilizing little more than the Groovy XMLRPC library I was able to implement a client service for the Jira XmlRpcService in minutes.

Nothing terribly complicated going on for this plugin. Aside from the XMLRPC library and one more jar it depends upon there’s a service which implements calls for all of the methods on the XmlRpcService interface and a ‘helper’ class that makes using it a little easier(removes the need to pass the host name into each method). And any controller injected with the service gets a withJira(hostname, Closure) method which wraps the ‘helper’ class. This might not be the optimal way to do things, but I was looking for some better experience with MOP’ing in Groovy along with this little project so it worked out perfectly for me.

The method added to Controller classes just creates a ‘helper’ and sets it as the delegate for the closure.

        cClass.metaClass.withJira = {String hostname, Closure closure ->
            def helper = delegate.jiraXmlRpcService.createHelper(hostname)
            closure.setDelegate(helper)
            closure.setResolveStrategy(Closure.DELEGATE_FIRST)
            closure()
        }

Calling the withJira method looks like this, along with minimal exception handling:

            try
            {
                def projects, priorities, serverInfo
                withJira(jiraInstance.baseUrl) {
                    def token = login(jiraInstance.userName, jiraInstance.password)
                    serverInfo = getServerInfo(token)
                    priorities = getPriorities(token)
                    projects = getProjectsNoSchemes(token)
                    logout(token)
                }
                [jiraInstance: jiraInstance, projects: projects, priorities: priorities, serverInfo: serverInfo]
            }
            catch (e)
            {
                flash.message = "Failed to load data from ${jiraInstance.baseUrl}"
                redirect(action: "list")
            }

The ‘helper’ class itself represents an experiment with the Groovy ‘methodMissing’ behaviour. The idea is to store the ‘hostname’ for a series of calls against the stateless service and add that as the first parameter for all wrapped methods. It was simple and quick, but right off the bat you lose the ability to use IDE syntax completion support on this object. I thought another possibility here would be to use the @Delegate annotation on the service and/or Closure currying to add the additional ‘hostname’ parameter to methods.

class JiraXmlRpcServiceHelper
{
    def hostname
    def JiraXmlRpcService service

    def methodMissing(String name, args)
    {
        assert hostname && service
        def method = service.metaClass.methods.find {it.name == name}
        if(!method)
        {
            throw new NotImplementedException("The $name method is not implemented for ${this.getClass()}")
        }

        def newArgs = [hostname]
        args.each{newArgs << it}
        return method.invoke(service, newArgs as Object[])
    }
}

This plugin works with Grails 1.2.0.RC1 and represents about 8 hours of work all told – and a lot of fun to make! Jira 4 is not too shappy either, especially with the GreenHopper plugin. But that’s a post for another day.

A special thank you to Grails in Action and this article by Ted Naleid – both were extremely helpful putting this together. If you care to download it and take a spin here it is. Feedback is always welcome!

V0.1 of JiraGrailsPlugin (42)
Reblog this post [with Zemanta]

Post to Twitter Tweet This Post

Lately I’ve been thinking about all the different ways to bring Groovy into a pure Java or command line environment, and ended up diving into some code to explore the various options. Turns out there’s definitely a good variety of options for running Groovy dynamically inside and out of a Java application. I started out on this page from the Groovy site.
In particular for the environments I’ve been working in lately it’s been important to be able to run the same code both from within a Java application and from the command line. It’s also been a ‘nice to have’ to be able to package a jar with a bunch of the same scripts compiled together. Using maven as a harness also has the benefit of allowing for testing compiled scripts directly through instantiation even though the intended usage is from within a Java app using one of these methods. Source code is available here on github.

Groovy on the command line

The quickest and simplest way to run a Groovy Script or Class, command line arguments are automatically marshalled into an ‘args’ String array. Please note that due to a problem I’m having with my syntax highlighter plugin the process execution is shown here in single quotes; the actual code requires a GString(double quoted) in order to do the replacement for the inline variable. " THAT Wordpress!

//the script
myArgs = args
result = args.join(' ')
println result
println myArgs

//...and the test
    void testGroovyCall()
    {
        def proc = 'groovy $groovyScriptOne Hello World'.execute()
        proc.waitFor()
        def result = proc.text.split()
        assert result[0] == 'Hello'
        assert result[1] == 'World'
    }

GroovyShell

This is the basis of Groovy script execution. The GroovyShell allows for executing scripts, passing in a particular Binding context that allows for bi-directional communication between the script and the calling code. Parameters can be passed into the executing script in the Binding and results can be stored there to be returned to the calling context. GroovyShell also allows for running a class from the ‘main’ method, passing in String arguments. It will also execute implementers of Runnable and test files for JUnit or TestNG. Script text can also be declared inline and executed in the same way as files on disk. All in all, pretty bloody handy. Here’s a straightforward example of running a dirt simple Groovy script and inspecting the results. Note that this isn’t executable as shown, but I’ll provide the full source code on github for anyone who wants a closer look. Note that I’m also passing in an ‘out’ variable in the Binding, which effectively redirect System.out to a specified Writer implementation – a nice touch for inspecting output.

//the script
myArgs = args
result = args.join(' ')
println result
println myArgs

 //...and the test
    void testGroovyShell()
    {
        Binding binding = helper.createBinding()
        def shell = new GroovyShell(binding)
        shell.evaluate(new File(groovyScriptOne))
        helper.assertBinding(binding)
    }

//...and the Binding creation/assertion
     def static args = ['Hello', 'World'].asImmutable()
     /**
     * Create a Binding with a single parameter to be passed to scripts and an 'out' Writer to redirect console output.
     */
    private Binding createBinding()
    {
        Binding binding = new Binding()
        def sWriter = new StringWriter()
        def pWriter = new PrintWriter(sWriter)
        binding.setVariable ('args', new ArrayList(args))
        binding.setVariable ('out', pWriter)
        return binding
    }

    /**
     * Assert that the expected 'common' actions are done with the Binding by each of the use cases.
     * The original 'args' should be as expected.
     * A copy of 'args' should have been placed in the Binding during execution.
     * The 'result' should be the concatentation of 'args' separated by spaces.
     */
    private def assertBinding(Binding binding)
    {
        assert binding.variables.size() == 4
        assert binding.variables.args.value[0].toString() == args[0]
        assert binding.variables.args.value[1].toString() == args[1]
        assert binding.variables.result.value.toString() == args.join(' ')
        assert binding.variables.myArgs.value[0].toString() == args[0]
        assert binding.variables.myArgs.value[1].toString() == args[1]
    }

GroovyScriptEngine

The GroovyScriptEngine enables dynamically running Groovy sources located in a fixed set of content roots, complete with reloading modified scripts in between executions. Running a Groovy script this way is essentially the same as using GroovyShell.

    void testGroovyScriptEngine()
    {
        Binding binding = helper.createBinding()
        def gse = new GroovyScriptEngine(new File('.').toURL())
        gse.run(groovyScriptOne, binding)
        helper.assertBinding(binding)
    }

GroovyClassLoader

An extension to URLClassLoader that enables parsing Groovy sources into Class representations. Once a Class object is created, instances of the class can be created easily and either cast to a known type or manipulated through convention by use of the standard Groovy ‘invokeMethod’. This works equally well on Groovy and Java btw. Here’s an example of running a Java class using GroovyClassLoader. In this case the Java file has a field called ‘binding’ and implements a ‘run’ method.

    /**
     * Dynamically compile, instantiate, inspect and call methods on a POJO.
     */
    void testGroovyClassLoaderOnJava()
    {
        GroovyClassLoader loader = new GroovyClassLoader();
        Class javaClass = loader.parseClass(new File(javaFileOne));

        def groovyObject = javaClass.newInstance();
        def binding = helper.createBinding()
        groovyObject.binding = binding
        if(groovyObject.metaClass.respondsTo(groovyObject, 'run'))
        {
            groovyObject.invokeMethod('run', null);
            helper.assertBinding(binding)
        }
        if(groovyObject.metaClass.respondsTo(groovyObject, 'main'))
        {
            groovyObject.invokeMethod('main', new ArrayList(helper.args) as String[]);
        }
    }

(Groovy)Console

The Console can be embedded in Java or Groovy code to provide a dynamic interactive Swing environment. This is the same UI spawned from the command line invocation of ‘groovyConsole’. Internally it uses GroovyShell for actual execution, and so can do everything that GroovyShell can do – plus a couple of additions. For one, you can add jars and/or directories to the classpath used when executing your scripts.
Groovy Console

The Best of Both Worlds – at Least for my use case

In actual practice these patterns can be used a lot more successfully by observing standard Java practices, like casting classes parsed using GroovyClassLoader to a known interface before interacting with them, or by using Classes to organize business logic inside of a Script that essentially functions as a ‘main’ method. This example defines two dependent internal classes, marshals parameters to them and then returns the results attached to the originally passed in Binding.

/**
 * Classes inside of a Script.
 */
class TestableClass
{
    Binding binding

    def run()
    {
        binding.with
        {
            setVariable('myArgs', getVariable('args'))
            setVariable('result', getVariable('args')?.join(' '))
        }
        return binding
    }
}

class TestableClass2
{
    Binding binding

    public TestableClass2(Binding binding)
    {
        this.binding = binding;
    }

    def run()
    {
        return new TestableClass(binding: binding).run()
    }
}

if (args)
{
    def internalBinding = new Binding()
    internalBinding.setVariable('args', new ArrayList(args))
    internalBinding = new TestableClass2(internalBinding).run()
    args = internalBinding.args
    myArgs = internalBinding.myArgs
    result = internalBinding.result  //return value from script
}
else
{
    println 'no args!!'
}

Summary of Groovy Execution Methods

MethodGroovy ScriptsGroovy ClassesJava
groovy exec on the command lineYes, passes in String command line argments in a variable called 'args'Yes, calls the main method with String argumentsNo
GroovyShellYes, parameters passed in a Binding object that the Script can mutateYes, calls the main method with String argumentsYes, no apparent way to pass arguments
GroovyScriptEngineYes, parameters passed in a Binding object that the Script can mutateYes, no apparent way to pass argumentsYes, no apparent way to pass arguments
GroovyClassLoaderYes, instantiate a parsed Class and either cast to a known type or use Groovy reflection methods to call methodsYes, instantiate a parsed Class and either cast to a known type or use Groovy reflection methods to call methodsYes, instantiate a parsed Class and either cast to a known type or use Groovy reflection methods to call methods
(Groovy)ConsoleSame as GroovyShellSame as GroovyShellSame as GroovyShell
Reblog this post [with Zemanta]

Post to Twitter Tweet This Post

25 Oct, 2009

Grails-UI DataTable using XML for a model

Posted by: TheKaptain In: Development

I had a great chance to play with some new stuff this weekend, namely Grails 1.2-M3, the new Grails REST plugin and Groovy in general. Awhile back I wrote some Groovy code to explore the various Jira, Fisheye and Crucible REST api’s using Apache HttpClient directly, and I wanted to see what it would like abstracted behind HTTPBuilder. With the help of the Grails-UI and Google-charts plugins, I got some pretty nice views of the data as well.

First off, dealing with a RESTful call was about as simple as I’ve ever seen. This is the entire code that deals with creating the connection, authenticating, executing a GET, and parsing the returned XML into a ‘data’ property on the response.

    private withFisheye(String url, Map args) {
        withRest(uri: url) {
            auth.basic userName, password
            return get(query: args)
        }
    }

Getting XML using Andres’ plugin is extremely simple and we can achieve some pretty nice visualizations of the resulting data very easily as well. In particular I wanted to share how to use an XML response as a backing model for DataTable. The excellent examples provided by Matthew Taylor on his blog seemed to concentrate on using GORM to load and sort domain objects to utilize as data models. When using XML as an alternative way to represent the data, and using RESTful calls to populate that data, the available sorting options on a DataTable weren’t able to function properly without a little extra help.

Consider an list of XML elements like this, which represents a single review in Crucible.

<reviewdata>
    <allowreviewerstojoin>false</allowreviewerstojoin>
    <author>
        <displayname>Kelly Robinson</displayname>
        <username>TheKaptain</username>
    </author>
    <closedate>20010101T00::00.0000000</closedate>
    <createdate>20010101T00::00.0000000</createdate>
    <creator>
        <displayname>Kelly Robinson</displayname>
        <username>TheKaptain</username>
    </creator>
    <description>
        Test review
    </description>
    <moderator>
        <displayname>Kelly Robinson</displayname>
        <username>TheKaptain</username>
    </moderator>
    <name>
        Test review
    </name>
    <permaid>
        <id>CR1</id>
    </permaid>
    <projectkey>CR</projectkey>
    <state>Closed</state>
    <summary>
      Test review
    </summary>
</reviewdata>

You can leverage this list as a DataTable model by extracting specific elements from the XML, and providing a sorting mechanism based on dynamic map value lookups.

    private def createReviewDataJson(HttpServletResponse response, Map params, reviews) {
        def list = []
        response.setHeader("Cache-Control", "no-store")
       //build a List of Maps, one for each row in the DataTable
        reviews.reviewData.each {
            list << [
                    id: it.permaId.id.text(),
                    author: it.author.displayName.text(),
                    creator: it.creator.displayName.text(),
                    moderator: it.moderator.displayName.text(),
                    description: it.description.text(),
                    state: it.state.text()
            ]
        }
       //sort by the 'order' and 'sort' parameters passed in by DataTable
        switch (params.order) {
            case 'asc':
                list.sort { it."${params.sort}" } //sort by value where key == params.sort
                break
            case 'desc':
                list.sort {a, b -> b."${params.sort}" <=> a."${params.sort}" } //reverse sort by value
                break
        }
       //the entire model
        def data = [totalRecords: list.size(), results: list]
        render data as JSON
    }

This model can then be rendered using the tag. Note that this is pretty much a direct copy of a provided example, nothing fancy here.

<gui:datatable id="statDataTable" draggablecolumns="true" columndefs="[
        [id:'id', sortable:true, resizeable:true],
        [author:'author', sortable:true, resizeable:true],
        [creator:'creator', sortable:true, resizeable:true],
        [moderator:'moderator',  sortable:true, resizeable:true],
        [description:'description', sortable:true, resizeable:true, formatter:'textarea'],
        [state:'state', sortable:true, resizeable:true]
    ]" paginatorconfig="[
        template:'{PreviousPageLink} {PageLinks} {NextPageLink} {CurrentPageReport}',
        pageReportTemplate:'{totalRecords} total records'
    ]" sortedby="id" controller="fisheye" action="${action}" resultslist="results" rowsperpage="10">

So for very little work you get a sortable, paginated DataTable, complete with column resizing and dragging. The DataTable is also being rendered using a template, allowing it to be used arbitrarily by controller methods that populate the model with different reviews. Pretty cool if you ask me. I also used the same backing XML model to drive some PieCharts, but that’s perhaps a topic for another post.

:)

Post to Twitter Tweet This Post

Get Adobe Flash playerPlugin by wpburn.com wordpress themes

About

Tales of development, life and the folly that goes along with both.

Tags

On Twitter

Powered by Twitter Tools