tag:blogger.com,1999:blog-69745193310136327642024-02-08T09:25:37.429-05:00Agile ICEDynamic languages, programming, and other tech odds and endsJeffrey Eriksonhttp://www.blogger.com/profile/05123996612107368819noreply@blogger.comBlogger23125tag:blogger.com,1999:blog-6974519331013632764.post-16271972882135509252009-12-10T09:58:00.001-05:002009-12-10T10:01:39.698-05:00Coding around Shiro security in Grails integration testsA number of our controllers work directly with the Shiro-authenticated user in a session, so when it comes to integration testing our controllers, we need a way of faking the Shiro actions. Groovy's metaprogramming techniques make it fairly easy.<br /><br />There are three main pieces to be aware of in the Shiro authentication workflow: a Subject, the SecurityManager, and SecurityUtils. Creating a fake Subject is easy; the two things in Subject we need to worry about are the "principal" (more or less the user name) and whether or not that user is authenticated. We'll crate a Map with some simple closures and cast it as a Subject we can use:<br /><pre class="brush:groovy"><br />import org.apache.shiro.subject.Subject<br /><br />def subject = [ getPrincipal: { "iamauser" },<br /> isAuthenticated: { true }<br /> ] as Subject<br /></pre><br />Now we can use that Subject wherever we need to return a subject for Shiro to act on.<br /><br />The next step is making sure we have a SecurityManager in our Shiro ThreadContext object. With the SecurityManager, the only thing we need to worry about is that it returns our subject, so we'll again fake that with a Map and the "as" keyword:<br /><pre class="brush:groovy"><br />import org.apache.shiro.util.ThreadContext<br /><br />ThreadContext.put( ThreadContext.SECURITY_MANAGER_KEY, <br /> [ getSubject: { subject } ] as SecurityManager )<br /></pre><br /><br />Finally, since using Shiro's SecurityUtils makes it easy to deal with security objects in our controller code, we'll want to make sure it returns the values we want. In our case, all we really needed was the subject:<br /><pre class="brush:groovy"><br />import org.apache.shiro.SecurityUtils<br /><br />SecurityUtils.metaClass.static.getSubject = { subject }<br /></pre><br /><br />That's it! In our controller test cases, we put that in our setUp() method, and we were then able to test our controllers that used Shiro's SecurityUtils to grab the current user like this:<br /><pre class="brush: groovy"><br />def user<br />def subject = SecurityUtils.subject<br />if (subject.authenticated) {<br /> user = ShiroUser.findByUsername( subject.principal )<br />} else {<br /> // do something different<br />}<br /></pre><br /><br />Putting together the pieces of the mock Shiro code looks like this:<br /><pre class="brush:groovy"><br />import org.apache.shiro.subject.Subject<br />import org.apache.shiro.util.ThreadContext<br />import org.apache.shiro.SecurityUtils<br /><br />def subject = [ getPrincipal: { "iamauser" },<br /> isAuthenticated: { true }<br /> ] as Subject<br /><br />ThreadContext.put( ThreadContext.SECURITY_MANAGER_KEY, <br /> [ getSubject: { subject } ] as SecurityManager )<br /><br />SecurityUtils.metaClass.static.getSubject = { subject }<br /></pre>Jeffrey Eriksonhttp://www.blogger.com/profile/05123996612107368819noreply@blogger.com5tag:blogger.com,1999:blog-6974519331013632764.post-68658301096585685862009-11-19T23:33:00.006-05:002009-11-21T06:20:40.148-05:00Running easyb stories in a Gradle buildRecently, I've felt like I've been fighting Maven for all but the simplest builds, so I've been exploring alternative build systems, notably <a href="http://www.gradle.org/">Gradle</a>. One thing, too, that's become really important to my build processes lately is running <a href="http://www.easyb.org/">easyb</a> tests, so I wanted to figure out how to use easyb in my Gradle builds.<br /><br />One of the nice things about Gradle is it makes good use of existing Ant tasks (why reinvent the wheel?), so integrating easyb is not difficult at all. The first step is adding the easyb artifact to the project dependencies. Unless your project is actually making use of easyb internally, you'll likely want to include it as a "testRuntime" dependency. The easyb artifact actually requires commons-cli, too, so you'll have to do one of two things:<br /><ul><br /><li>If you have your Gradle build set up to resolve transitive dependences with a Maven pom or Ivy file, you can set up your dependency definition to resolve transitive dependencies.</li><br /><li>If you're including the easyb jar directly via some other means, you can add a second "testRuntime" dependency for commons-cli.</li><br /></ul><br />The dependencies section might end up looking something like this:<br /><pre class="brush: groovy"><br />// Access via Maven repo, 0.9.6 is currently the latest available<br />testRuntime("org.easyb:easyb:0.9.6@jar") { transitive = true }<br /><br />// Access via local artifacts<br />testRuntime "org.easyb:easyb:0.9.7@jar"<br />testRuntime "commons-cli:commons-cli:1.2@jar"<br /></pre><br /><br />With the dependencies in place, it's next a matter of configuring easyb to run in a Gradle task. Again, there are two options here:<br /><ul><br /><li>You can set up a separate task to run your easyb stories if you want to keep them separate.</li><br /><li>You can add the easyb run to an existing task like "check" if you know you always want to run your easyb stories whenever other tests are run.</li><br /></ul><br />In either case, you first need to add the easyb task via Ant's "taskdef":<br /><pre class="brush: groovy"><br />ant.taskdef(name: "easyb", classname:"org.easyb.ant.BehaviorRunnerTask", <br /> classpath: sourceSets.test.runtimeClasspath.asPath)<br /></pre><br /><br />Next, you set up the easyb Ant task, telling it the classpath to use, where to put the reports and how to format them, along with where to find the behaviors you want to run:<br /><pre class="brush: groovy"><br />ant.easyb( classpath: sourceSets.test.runtimeClasspath.asPath ) {<br /> // assume testResultsDir has already been created<br /> report( location:"${project.testResultsDir}/story.txt", format:"txtstory" )<br /> behaviors( dir: "src/test/stories" ) {<br /> include( name:"**/*.story" )<br /> }<br /> }<br /></pre><br /><br />The "format" attribute can have a value of "html", "xml", "txtstory", or "txtspecification". For more information about those output formats, see <a href="http://www.easyb.org/running.html">the easyb documentation</a>. Note, at this time, it doesn't appear possible to output multiple formats at once; if you require multiple formats, one workaround, depending on how extensive your tests are, might be to run easyb multiple times, once for each output format you want.<br /><br />Finally, the easyb Ant task provides a "failureProperty" attribute naming a build property that will be set if any easyb story results in a failure. Since Gradle sees running easyb as a successful outcome and will happily keep chugging along as long as easyb ran without error, you can use the "failureProperty" in conjunction with Ant's "fail" task to fail the build if a story does not pass:<br /><pre class="brush: groovy"><br />// easyb task configured with failureProperty<br />ant.easyb( classpath: sourceSets.test.runtimeClasspath.asPath, failureProperty:'easyb_failed' ) {<br /> report( location:"${project.testResultsDir}/story.txt", format:"txtstory" )<br /> behaviors( dir: "src/test/stories" ) {<br /> include( name:"**/*.story" )<br /> }<br /> }<br /><br />// checking the failureProperty<br />ant.fail( if:'easyb_failed', message: 'Failures in easyb stories' )<br /></pre><br /><br />The final code in the build.gradle file, with dependencies defined and easyb added to Gradle's "check" task, might end up looking something like this:<br /><pre class="brush: groovy"><br />dependencies {<br /> testRuntime("org.easyb:easyb:0.9.5.2@jar") { transitive = true }<br />}<br /><br />check << {<br /><br /> ant.taskdef(name: "easyb", classname:"org.easyb.ant.BehaviorRunnerTask", classpath: sourceSets.test.runtimeClasspath.asPath)<br /><br /> ant.easyb( classpath: sourceSets.test.runtimeClasspath.asPath, failureProperty:'easyb_failed' ) {<br /> report( location:"${project.testResultsDir}/story.txt", format:"txtstory" )<br /> behaviors( dir: "src/test/stories" ) {<br /> include( name:"**/*.story" )<br /> }<br /> }<br /><br /> ant.fail( if:'easyb_failed', message: 'Failures in easyb stories' )<br />}<br /></pre><br /><br />When the build is run (in this case, on a Groovy project), the output might look like this:<br /><pre class="brush: shell"><br />user$ gradle clean check<br />:clean<br />:compileJava<br />:compileGroovy<br />:processResources<br />:classes<br />:compileTestJava<br />:compileTestGroovy<br />:processTestResources<br />:testClasses<br />:test<br />:check<br /><br />BUILD SUCCESSFUL<br /><br />Total time: 7.267 secs<br /></pre><br /><br /><br />If there are problems, or if any of your stories fail and you're failing the build based on the "failureProperty", then you might see output like this:<br /><br /><pre class="brush: shell"><br />user$ gradle clean check<br />:clean<br />:compileJava<br />:compileGroovy<br />:processResources<br />:classes<br />:compileTestJava<br />:compileTestGroovy<br />:processTestResources<br />:testClasses<br />:test<br />:check<br /><br />FAILURE: Build failed with an exception.<br /><br />* Where:<br />Build file '/path/to/project/build.gradle' line: 39<br /><br />* What went wrong:<br />Execution failed for task ':check'.<br />Cause: Failures in easyb stories<br /><br />* Try:<br />Run with -s or -d option to get more details. Run with -S option to get the full (very verbose) stacktrace.<br /><br />BUILD FAILED<br /><br />Total time: 7.443 secs<br /></pre><br /><br />Note, if the build fails, and you haven't yet successfully run easyb in Gradle yet, you might not have it configured correctly. However, the "normal" output isn't particularly helpful in telling you what's wrong, since Gradle seems to supress most of the error output. One of the more helpful things at that point is to run your build using the "-d" option to get the full debugging output:<br /><pre class="brush: shell"><br />gradle -d clean check<br /></pre><br /><br />With the extensive debugging output, you should be able to trace through the build and see what's going on; often, the problem is a "ClassDefNotFound" error as a result of an artifact missing from the dependencies or an error in parsing your easyb stories or something along those lines.Jeffrey Eriksonhttp://www.blogger.com/profile/05123996612107368819noreply@blogger.com4tag:blogger.com,1999:blog-6974519331013632764.post-62568947618011442942009-11-14T11:16:00.001-05:002009-11-14T14:52:48.822-05:00Writing a simple easyb pluginNOTE: I wrote this article up, published it, then found <a href="http://code.google.com/p/easyb/wiki/PluginAPI">this PluginAPI wiki article</a> on the easyb site. The only difference I saw was the package names of the classes involved. Just in case this article provides a bit of clarification, I'll keep it around. . . .<br /><br />The <a href="http://www.easyb.org/">easyb BDD framework</a> provides a ton of great functionality out of the box, but as with anything, sometimes there are features that you want that the developers can't predict. The easyb developers realized this and created a framework for adding plugins to extend easyb and make it do what you need it to.<br /><br />Plugins for easyb implement the EasybPlugin interface, basically providing behavior before and after easyb "events" (by "events", I mean when easyb runs somethng like "given" or "scenario"). The EasybPlugin interface looks like this:<br /><pre class="brush: groovy"><br />package org.easyb.plugin<br /><br />interface EasybPlugin {<br /> String getName()<br /> def beforeScenario(Binding binding)<br /> def afterScenario(Binding binding)<br /><br /> def beforeGiven(Binding binding)<br /> def afterGiven(Binding binding)<br /><br /> def beforeWhen(Binding binding)<br /> def afterWhen(Binding binding)<br /><br /> def beforeThen(Binding binding)<br /> def afterThen(Binding binding)<br /><br /> def beforeStory(Binding binding)<br /> def afterStory(Binding binding)<br /><br /> void setClassLoader(ClassLoader classLoader)<br />}<br /></pre><br /><br />Most of the time, however, you probably don't need to provide actions for *every* event, so instead of implementing EasybPlugin, you can just extend BasePlugin which provides no-op implementations of the "event" methods, overriding whichever methods you need.<br /><br />Let's get into an example. Let's say we want to extend easyb to mimic injecting resources into a story run with the <a href="http://grails.org/plugin/easybtest">Grails easyb plugin</a> (see my post <a href="http://agileice.blogspot.com/2009/11/injecting-resources-in-easyb-grails.html">here</a> for the story behind that). The first thing we want to do is set up our Groovy class and implement the one abstract method in BasePlugin, getName():<br /><pre class="brush: groovy"><br />class GrailsInjectPlugin extends BasePlugin {<br /> public String getName() { "grails-inject" }<br />}<br /></pre><br /><br />The getName() method serves two purposes: first, in the easyb story, you'll have a "using" line with the value that getName() returns, signaling easyb to use the plugin. Second, easyb will use this name to lookup the plugin via its PluginLocator class.<br /><br />At this point, we could compile and include the plugin, and it would be valid, but it wouldn't actually do anything. To extend easyb's behavior, we need to override one of the "event" methods. In the case of injecting Grails resources, we want to set up our resources before an entire story executes (similar to how they'd be initialized in a Grails test, def-ing them at the beginning of a test class). We'll override the beforeStory() method:<br /><pre class="brush: groovy"><br /> def beforeStory(Binding binding) {<br /> binding.inject = { beanName -><br /> binding."${beanName}" = <br /> ApplicationHolder.application.mainContext.getBean(beanName)<br /> }<br /> }<br /></pre><br /><br />The "event" methods get passed a Binding implementation which basically is what easyb will use to look up values, methods, and the like that it encounters in its stories. In our beforeStory() implementation, we're telling the binding that it now has an "inject" method that takes a bean name as an argument. The method looks up that bean in the Grails Spring context, then, in the binding, associates the bean with the passed in bean name.<br /><br />The final code for the plugin class looks like this:<br /><pre class="brush: groovy"><br />package com.agileice.easyb.plugin<br /><br />import org.codehaus.groovy.grails.commons.ApplicationHolder<br />import org.easyb.plugin.BasePlugin<br /><br />class GrailsInjectPlugin extends BasePlugin {<br /><br /> public String getName() { "grails-inject" }<br /><br /> def beforeStory(Binding binding) {<br /> binding.inject = { beanName -><br /> binding."${beanName}"= <br /> ApplicationHolder.application.mainContext.getBean(beanName)<br /> }<br /> }<br />}<br /></pre><br /><br />It's all fairly simple and straightforward . . . the easyb developers did a great job in making plugin development easy.<br /><br />The next step in getting the plugin into your application is to include it in a JAR file. In addition to our plugin classes, we need to include some information in the JAR's META-INF directory. When easyb is looking for plugin implementations, it uses the sun.misc.Service class, so we need to include a file named org.easyb.plugin.EasybPlugin in the JAR's META-INF/services directory to tell the Service class that we provide an implementation of EasybPlugin. That file will contain the name of our implementation class:<br /><pre class="brush: text"><br />com.agileice.easyb.plugin.GrailsInjectPlugin # inject Grails beans<br /></pre><br /><br />At this point, we can compile our plugin, JAR up our classes and the META-INF information, and with the JAR on the classpath, run our easyb stories. To use the plugin in a story, we include a "using" line with the name of our plugin (the value returned by the getName() method). With the plugin included, we can use the keywords we've defined:<br /><pre class="brush: groovy"><br />using "grails-inject"<br /><br />inject "grailsApplication"<br />inject "someService"<br /><br />scenario "Grails App injection", {<br /><br /> given "injected Grails resources"<br /> then "the Grails application should not be null", {<br /> grailsApplication.shouldNotBe null<br /> }<br /> and "the service instance should not be null", {<br /> someService.shouldNotBe null<br /> }<br />}<br /></pre><br /><br />Now, when the story runs, easyb should pick up our plugin, handle our behavior, and execute our scenarios. Note, the above examples should work with the version of easyb included with the Grails easyb plugin (marked 0.9.7). If you're working with an older version (say, from a Maven repository where the latest version is 0.9.5), you'll probably have to implement all of EasybPlugin yourself (since it looks like BasePlugin doesn't exist there), changing the "def" for each method to "void". Once you do that, everything else should work the same.Jeffrey Eriksonhttp://www.blogger.com/profile/05123996612107368819noreply@blogger.com1tag:blogger.com,1999:blog-6974519331013632764.post-25908702027856374482009-11-13T23:03:00.008-05:002009-11-26T20:14:14.829-05:00Injecting resources in easyb Grails stories<span style="font-weight:bold;">Note: the functionality described in this post and the which the plugin described below provides have been incorporated into the latest version of the easyb Grails plugin (plugin version 1.2). I'll leave this post here for historical context.</span><br /><br />Normally, when you're writing Grails tests, you can have Grails inject things like service instances or the Grails application itself by simply def-ing them in your test case:<br /><pre class="brush: groovy"><br />class MyTests {<br /> def grailsApplication<br /> def someService<br />}<br /></pre><br /><br />However, when you're working with with the <a href="http://www.easyb.org/">easyb</a> <a href="http://grails.org/plugin/easybtest">Grails plugin</a>, the stories and specifications don't go through the same process as the standard tests, so you can't just def something at the beginning of the story and access it in the scenarios.<br /><br />Instead, you have to access things through the Grails <a href="http://grails.org/doc/1.1.x/api/org/codehaus/groovy/grails/commons/ApplicationHolder.html">ApplicationHolder</a>, a class that exists only to provide access to the GrailsApplication instance. Once you have the application instance (and through that, the main Spring context), you can use the getBean() method to reference things that you'd normally have injected:<br /><pre class="brush: groovy"><br />import org.codehaus.groovy.grails.commons.ApplicationHolder<br />. . .<br />ApplicationHolder.application.mainContext.getBean("someService")<br /></pre><br /><br />Putting that all together with a story might look something like this:<br /><pre class="brush: groovy"><br />import org.codehaus.groovy.grails.commons.ApplicationHolder<br /><br />scenario "Grails App injection", {<br /><br /> given "service instances initialized from Grails ApplicationHolder", {<br /> grailsApplication = ApplicationHolder.application<br /> someService = ApplicationHolder.application.mainContext.getBean("someService")<br /> }<br /> then "the Grails application should not be null", {<br /> grailsApplication.shouldNotBe null<br /> }<br /> and "the service instance should not be null", {<br /> someService.shouldNotBe null<br /> }<br /><br />}<br /></pre><br /><br />While that's not too bad, it's actually a good bit more noise than I'd like, especially since I can see doing this often in my Grails integration tests. To make it a little easier to read, I ended up writing an easyb plugin to make it look like I was actually injecting things in the easyb stories (I wrote up the process I used <a href="http://agileice.blogspot.com/2009/11/injecting-resources-in-easyb-grails.html">here</a> . . . there's also a good wiki entry about <a href="http://code.google.com/p/easyb/wiki/PluginAPI">the Plugin API</a> at the easyb site). With the plugin I wrote (jar file available <a href="https://sourceforge.net/projects/grails-inject/">here</a> under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>, though it's subject to change as I learn more about easyb . . . the source will eventually be available if people find it useful), I can write a story with easyb's "using" syntax to include the plugin and the custom "inject" keyword:<br /><pre class="brush: groovy"><br />using "grails-inject"<br /><br />inject "grailsApplication"<br />inject "someService"<br /><br />scenario "Grails App injection", {<br /><br /> given "Service instances initialized from Grails ApplicationHolder"<br /> then "the Grails application should not be null", {<br /> grailsApplication.shouldNotBe null<br /> }<br /> and "the service instance should not be null", {<br /> someService.shouldNotBe null<br /> }<br /><br />}<br /></pre><br /><br />With the instances injected into my tests, I can now call whatever methods I want on them, dealing with them in the same way I would in a standard Grails test case. NOTE: if you want to use the plugin above, download it and drop it in the lib directory of your Grails app. When you run "grails easyb-test", easyb should pick it up and make the syntax available to your stories and specifications.Jeffrey Eriksonhttp://www.blogger.com/profile/05123996612107368819noreply@blogger.com3tag:blogger.com,1999:blog-6974519331013632764.post-26587984588191937092009-11-09T07:26:00.007-05:002009-11-09T16:17:03.063-05:00Getting started with the easyb plugin for BDD in GrailsOne of the more exciting things I've learned about recently is doing behavior driven development (BDD) with a framework called <a href="http://www.easyb.org/">easyb</a>. Easyb allows you to test your system by defining behavior in stories and specifications in a way that allows your "non-developer" stakeholders to understand them relatively easily. I also find that it helps me think more clearly about what my systems should actually be doing and how the pieces should interact. Like I said, I'm really excited by it, and I really wanted to start incorporating easyb where I can. Since I've been doing a ton of Grails work lately, naturally I wanted to try to incorporate it into my Grails workflow. Fortunately, there's a plugin for that, the Grails easyb plugin.<br /><br />The first step in doing BDD with easyb in Grails is, of course, to install the plugin, and you do that in the same way you install any other Grails plugin: in your project directory, issue the command "grails install-plugin easyb". After all the noise of starting Grails and downloading the plugin artifact, you'll see:<br /><pre class="brush: text"><br />Plug-in provides the following new scripts:<br />------------------------------------------<br />grails easyb-test<br /></pre><br /><br />Now we can mix easyb stories and specifications in with the usual Grails tests and run them using "grails easyb-test" command. Note, however, that at this point, to execute both your easyb and usual Grails tests, you have to run two commands, both "grails test-app" and "grails easyb-test": just running the normal "test-app" won't also execute the easyb tests, and running the easyb tests won't also execute the normal tests.<br /><br />So let's say I'm working with an application that takes dry cleaning orders and I want to test the behavior of the service that creates orders when a customer drops of some suits to be dry cleaned. Assuming I have a class called DropOffService, I'll create a new file in the test/unit directory, calling it either DropOffService.story or DropOffServiceStory.groovy (either will work).<br /><br />Now I can define the behavior I want in the story file. I won't go in-depth on the details of writing easyb stories since there's <a href="http://www.easyb.org/dsls.html">good documentation</a> on the easyb site for that, but the short form is that I create scenarios with given conditions, some event that occurs, and a pre-defined outcome. To test our service's behavior, I might define the story like this:<br /><pre class="brush:groovy"><br />scenario "customer drops off suits", {<br /> given "a drop-off service"<br /> and "a customer with suits"<br /> when "the customer drops off the suits"<br /> then "the service should generate a new order"<br />}<br /></pre><br /><br />At this point, I haven't actually written any code that will exercise the service, but I can still run "grails easyb-test". When I do, the plugin looks for valid easyb stories and specifications, runs them, and generates reports in the test/reports directory. The easyb plugin generates both text and html reports just like the standard Grails tests; however, it also produces XML output, too, potentially useful for reporting in something like a continuous integration system. Unlike the standard Grails reporting, instead of getting a file for each test class, the easyb plugin generates a report for each *type* of test. So we end up with a reports listing that looks like this:<br /><pre class="brush: text"><br />test/reports/html:<br />easyb-functional.html easyb_img04.jpg easyb_report.css<br />easyb_img01.gif easyb_img05.jpg easyb_spacer.gif<br />easyb_img02.jpg easyb_img06.jpg easyb-unit.html<br />easyb_img03.jpg easyb-integration.html prototype.js<br /><br />test/reports/plain:<br />specifications-functional.txt stories-functional.txt<br />specifications-integration.txt stories-integration.txt<br />specifications-unit.txt stories-unit.txt<br /><br />test/reports/xml:<br />easyb-functional.xml easyb-integration.xml easyb-unit.xml<br /></pre><br /><br />If we actually look at the reports, we'll see that the single scenario I've written has a result of "pending" since I haven't actually implemented any code to exercise the drop-off service. At the point where I actually *do* something in the story, the result will change depending on whether or not the scenario produces the outcome I'm expecting.<br /><br />So there's the basics of using easyb with Grails. There's definitely more to explore beyond this simple example (testing controllers, using dependency injection, and such), and I'll do that in future postings.Jeffrey Eriksonhttp://www.blogger.com/profile/05123996612107368819noreply@blogger.com8tag:blogger.com,1999:blog-6974519331013632764.post-7433751547304462912009-09-19T11:53:00.005-04:002009-09-19T22:13:33.786-04:00Binding the Grails DataSource in JNDI for Integration TestingOne of the components of the Grails application we're working on requires a database connection to be looked up via JNDI. That's fine for running in an application container in production where we can configure JNDI data sources easily enough, but for our integration tests using the embedded HSQLDB, we needed a way to get the Grails-configured testing data source via JNDI.<br /><br />While we could have set up a source in jetty-env.xml and placed that file in WEB-INF, from a number of postings on the 'net (see, for example, <a href="http://www.nabble.com/JNDI-and-Jetty-td24922531.html">this thread</a>), it seems like the integration tests don't actually run within the web application context Jetty provides. So, instead, we decided to register the data source programmatically as we needed it in our integration tests.<br /><br />Fortunately, Grails provides access easily enough to the testing data source (configured in grails-app/conf/DataSource.groovy) merely by adding a "def dataSource" in our integration test class defintion:<br /><pre class="brush: groovy"><br />class MyClassTests extends GroovyTestCase {<br /> def dataSource // auto-wired by Grails<br /><br /> . . . setup, test methods, etc . . .<br />}<br /></pre><br />With the data source defined, we can now access it as we need it.<br /><br />The next step is to create an <a href="http://java.sun.com/javase/6/docs/api/javax/naming/InitialContext.html">InitialContext</a> and bind the data source:<br /><pre class="brush: groovy"><br />def ctx = new javax.naming.InitialContext()<br />ctx.bind("java:/testing-db", dataSource)<br /></pre><br /><br />Now, with the data source bound in JNDI, we can retrieve it and use it where we need it:<br /><pre class="brush: groovy"><br />def ctx = new javax.naming.InitialContext()<br />def conn = ctx.lookup("java:/testing-db")<br />def sql = new groovy.sql.Sql(conn)<br /><br />// create a table to hold some test data<br />sql.execute("create table test_data(id identity, some_column varchar, col_ts timestamp default current_timestamp)")<br /></pre><br /><br />Of course, if we didn't want to worry about accidentally messing up the Grails testing data source, we could always have set up our own HSQLDB data source and bound it:<br /><pre class="brush: groovy"><br />import org.apache.commons.dbcp.BasicDataSource<br /><br />def ds = new BasicDataSource()<br />ds.setUrl("jdbc:hsqldb:mem:myTestDb")<br />ds.setUsername("sa")<br />ds.setPassword("")<br />ds.setDriverClassName("org.hsqldb.jdbcDriver")<br /><br />def ctx = new InitialContext()<br />ctx.bind("java:/testing-db", ds)<br /></pre><br /><br />However, in our case, using the standard Grails data source worked just fine. It's probably worth our while to try to set up a data source through jetty-env.xml for using our components requiring JNDI in the "run-app" development environment, but our integration tests are running, and that's good enough for now.Jeffrey Eriksonhttp://www.blogger.com/profile/05123996612107368819noreply@blogger.com2tag:blogger.com,1999:blog-6974519331013632764.post-65219430013369515332009-09-18T07:02:00.007-04:002009-11-14T17:47:16.467-05:00Pretty-printing XML results returned from Groovy RESTClientIn <a href="http://agileice.blogspot.com/2009/08/groovy-restclient-httpbuilder-and-put.html">another blog post here</a>, someone <a href="http://agileice.blogspot.com/2009/08/groovy-restclient-httpbuilder-and-put.html?showComment=1253223947822#c5601448145019323643">commented</a> that they had to fall back to <a href="http://groovy.codehaus.org/modules/http-builder/">HTTPBuilder</a> to output the XML returned from a REST request because <a href="http://groovy.codehaus.org/modules/http-builder/doc/rest.html">RESTClient</a> automatically parses the XML and returns a <a href="http://groovy.codehaus.org/api/groovy/util/slurpersupport/GPathResult.html">GPathResult</a> <a href="http://groovy.codehaus.org/api/groovy/util/slurpersupport/NodeChild.html">NodeChild</a> object. That's certainly one solution (and it gives you a good amount of control over both the request and its output), but if you *really* want to use RESTClient, it's still possible to format the results parsed via <a href="http://groovy.codehaus.org/Reading+XML+using+Groovy%27s+XmlSlurper">XMLSlurper</a>.<br /><br />When I needed to do this, I ended up using a combination of Groovy's <a href="http://groovy.codehaus.org/Creating+XML+using+Groovy%27s+StreamingMarkupBuilder">StreamingMarkupBuilder</a> to create the initial output, then I used <a href="http://xml.apache.org/xalan-j/">Xalan</a> to transform that output into easier to read XML. The method ended up looking like this:<br /><pre class="brush: groovy"><br />import groovy.xml.StreamingMarkupBuilder<br /><br />import javax.xml.transform.TransformerFactory<br />import javax.xml.transform.Transformer<br />import javax.xml.transform.OutputKeys<br />import javax.xml.transform.stream.StreamResult<br />import javax.xml.transform.stream.StreamSource<br /><br />/**<br /> * pretty prints the GPathResult NodeChild<br /> */<br />def outputFormattedXml(node) {<br /> def xml = new StreamingMarkupBuilder().bind {<br /> mkp.declareNamespace("":node.namespaceURI())<br /> mkp.yield(node)<br /> }<br /><br /> def factory = TransformerFactory.newInstance()<br /> def transformer = factory.newTransformer()<br /> transformer.setOutputProperty(OutputKeys.INDENT, 'yes')<br /><br /> // figured this out by looking at Xalan's serializer.jar<br /> // org/apache/xml/serializer/output_xml.properties<br /> transformer.setOutputProperty("{http\u003a//xml.apache.org/xalan}indent-amount", "2")<br /> def result = new StreamResult(new StringWriter())<br /> transformer.transform(new StreamSource(new ByteArrayInputStream(xml.toString().bytes)), result)<br /><br /> return result.writer.toString()<br />}<br /></pre><br /><br />As I mentioned in the code comments, there were some pieces I had to figure out from looking in Xalan's serializer.jar. For modifying other output properties, take a look at org/apache/xml/serializer/output_xml.properties in serializer.jar to see just what you can customize and how to refer to it in your code.<br /><br />In the end, the above method could probably be used to pretty-print any NodeChild object from GPathResult. There may be an easier or "more Groovy" way to output this kind of thing, but this allows the use of both the easy-to-use RESTClient and the easy-to-use XmlSlurper without having to worry much about making the output human-readable.Jeffrey Eriksonhttp://www.blogger.com/profile/05123996612107368819noreply@blogger.com5tag:blogger.com,1999:blog-6974519331013632764.post-69795117956726743892009-09-15T15:18:00.001-04:002009-09-15T15:18:45.171-04:00Grails type conversion outside of domain objectsIn a recent Grails project, we needed a way to do type conversion outside of merely marshalling values for a domain object (i.e. outside of, say, automatically loading up the properties of a domain object from request parameters, a job which Grails does really well). Specifically, we needed to convert the String representation of a Date into an actual Date object for use in our domain object's findByLastUpdatedGreaterThan() method. Initially, we hoped the method would automatically convert the type for us, but instead it threw exceptions saying "No signature of method . . . is applicable for argument types" because it couldn't handle a String instead of a Date.<br /><br />When Grails converts types for marshalling request parameters to domain objects, behind the scenes, it uses a GrailsDataBinder instance, converting values in the process of loading up the object's properties. And while the GrailsDataBinder implements Spring's TypeConverter and gives us access to the convertIfNecessary() method, it also requires a domain object instance in its constructor so it has a target to bind values to. Since all we were doing is simple type conversion, we wanted a different way.<br /><br />Enter Spring's <a href="http://static.springsource.org/spring/docs/2.5.6/api/org/springframework/beans/SimpleTypeConverter.html">SimpleTypeConverter</a>, a class that really only does one thing: convert from a String type to an instance of a target class. SimpleTypeConverter allows us to register custom property editors, the backbone of the type conversion process, so the first task was to implement a <a href="http://java.sun.com/javase/6/docs/api/java/beans/PropertyEditor.html?is-external=true">PropertyEditor</a> (extending <a href="http://java.sun.com/javase/6/docs/api/java/beans/PropertyEditorSupport.html">PropertyEditorSupport</a>) that would let us take a series of date formats and parse them to a Date. Thanks to some very detailed information in a response to this <a href="http://stackoverflow.com/questions/963922/grails-date-unmarshalling">StackOverflow Question</a>, implementing our CustomDateEditor was fairly easy:<br /><pre class="brush: groovy"><br />import java.beans.PropertyEditorSupport<br />import java.text.SimpleDateFormat<br />import java.text.ParseException<br /><br />/**<br /> * A property editor that allows for handling many different<br /> * date formats at once (as opposed to Spring's default CustomDateEditor<br /> * which only handles one date format configured at instantiation)<br /> *<br /> * This class is modified from information found at:<br /> * http://stackoverflow.com/questions/963922/grails-date-unmarshalling<br /> */<br />class CustomDateEditor extends PropertyEditorSupport {<br /><br /> private final List< String> formats<br /><br /> CustomDateEditor() {<br /> // in our production code, we get the formats from our Grails config<br /> def formats = [ "yyyyMMdd-HHmmss", "yyyy-mm-dd HH:mm:ss.S" ]<br /> List< String> formatList = new ArrayList< String>(formats.size())<br /> formats.each { format -><br /> formatList << format.toString() // Force String values (eg. for GStrings)<br /> }<br /> this.formats = Collections.unmodifiableList(formatList)<br /> }<br /><br /> def String getAsText() {<br /> return this.value.toString()<br /> }<br /><br /> def void setAsText(String s) throws IllegalArgumentException {<br /> if (s) {<br /> formats.each { format -><br /> def df = new SimpleDateFormat(format)<br /> try {<br /> this.value = df.parse(s)<br /> return<br /> } catch (ParseException e) {<br /> // Ignore<br /> }<br /> }<br /> }<br /> }<br />}<br /></pre><br /><br />Next, we wanted to make this custom Date editor available across the application, so we added it to our resources.groovy Spring config:<br /><pre class="brush: groovy"><br />beans = {<br /> customDateEditor(CustomDateEditor) { bean -><br /> bean.singleton = false // editors store state so are not thread-safe<br /> }<br />}<br /></pre><br />Now anywhere we wanted to do type conversion, all our classes needed to do was create a new SimpleTypeConverter, get a CustomDateEditor instance from Spring, and register that editor with the SimpleTypeConverter:<br /><pre class="brush: groovy"><br />// grailsApplication auto-wired by Grails<br />def editor = grailsApplication.mainContext.getBean("customDateEditor") <br />def converter = new SimpleTypeConverter()<br />converter.registerCustomEditor( Date.class, editor )<br /></pre><br /><br />With the converter set up and our custom Date editor registered, it was now a simple matter of doing the conversion:<br /><pre class="brush: groovy"><br />// NOTE: production code determines type dynamically from field being queried<br />def type = Date.class<br />def converted = converter.convertIfNecessary( value, type )<br /></pre><br /><br />If we had wanted to make our custom editor available for marshalling values to a domain object, we could have easily created an PropertyEditorRegistrar object and configured it via Spring so Grails would automatically use our property editor (as described in the <a href="http://stackoverflow.com/questions/963922/grails-date-unmarshalling">StackOverflow Question</a> above). But, again, all we wanted was fairly straightforward type conversion outside of a domain object. The combination of Spring's SimpleTypeConverter and our CustomDateEditor gave us that.Jeffrey Eriksonhttp://www.blogger.com/profile/05123996612107368819noreply@blogger.com6tag:blogger.com,1999:blog-6974519331013632764.post-19855984916444791262009-09-11T06:53:00.005-04:002009-09-11T07:38:02.286-04:00Grails integration testing: GroovyTestCase v. GrailsUnitTestCaseWorking on a Grails project in IntelliJ over the last few weeks, I've accumulated a number of unit and integration tests for various classes. Up until now, since I've only been working on isolated sections, I've been running the test classes individually, but I finally did a refactor that cut across a number of areas that really required me to run most of the tests. Since I was feeling a bit fuzzy headed with a late-summer cold, I started running the tests one by one, each one passing, but I quickly realized that was going to be a major pain.<br /><br />Since Grails allows you to run all the tests at once, I figured I'd just run "grails test-app" and be done with it, but to my surprise, a number of tests which had passed when I ran them individually failed when I ran the tests in one batch. Looking more closely and doing a bit more logging, it turned out that my controller classes that did content negotiation and used a "withFormat" block to check for XML content weren't handling the XML content: they were either running the html/form section rather than the section for handling xml content or they were running nothing at all.<br /><br />After a couple hours of head scratching and trying different approaches, it looked like the Grails configuration properties (which contain pieces telling Grails how to deal with Accept headers and different MIME types) weren't being made available to test cases in the integration tests. In a bit of desperation, I basically put the configuration parameters for doing content negotiation in one of my controller integration test case's setUp() methods:<br /><pre class="brush: groovy"><br />def grailsApplication<br />void setUp() {<br /> super.setUp()<br /> grailsApplication.config.grails.mime.file.extensions = true<br /> grailsApplication.config.grails.mime.use.accept.header = true<br /> grailsApplication.config.grails.mime.types = [ html: ['text/html','application/xhtml+xml'],<br /> xml: ['text/xml', 'application/xml'],<br /> text: 'text/plain',<br /> js: 'text/javascript',<br /> rss: 'application/rss+xml',<br /> atom: 'application/atom+xml',<br /> css: 'text/css',<br /> csv: 'text/csv',<br /> all: '*/*',<br /> json: ['application/json','text/json'],<br /> form: 'application/x-www-form-urlencoded',<br /> multipartForm: 'multipart/form-data'<br /> ]<br />}<br /></pre><br /><br />Magically, it worked. And not only that, it magically also made the other controller tests work, too, even without editing their setUp() methods. It seemed something was bleeding over and/or not getting cleaned up somewhere.<br /><br />I mentioned all this chatting with my friend Eric (see his blog at <a href="http://swordsystems.com/">Sword Systems</a> for some really great insights on Java, Groovy, and tools of the trade) who proceeded to tell me that he discovered some weirdness with GrailsUnitTestCase and how it mucked with the environment. I looked at the test cases I had (mostly generated automatically by Grails/IntelliJ), and they were a mix of GrailsUnitTestCase (integration tests for domain classes) and GroovyTestCase (integration tests for controllers, the failing tests). It turns out that the GroovyTestCase tests would work just fine on their own, but when mixed in the same environment with the GrailsUnitTestCase, somehow they lost their access to the Grails config.<br /><br />Doing a bit more research, I found <a href="http://jira.codehaus.org/browse/GRAILS-5071">this Grails bug report</a>, which mentions that "GrailsUnitTestCase sets grailsApplication.config to null in its tearDown routine which causes any additional tests . . ." to have problems. It seems even with this known problem, Grails still generates integration tests extending from GrailsUnitTestCase.<br /><br />So the solution was to use GrailsUnitTestCase (or its derivatives like ControllerUnitTestCase) *only* for unit tests (in spite of the examples at pages like <a href="http://grails.org/Testing+Controllers">Grails - Testing Controllers</a>); for integration tests, use GroovyTestCase (like the examples in the <a href="http://grails.org/doc/1.1.x/guide/9.%20Testing.html">main Grails documentation on testing</a>). Once I changed all my integration tests to GroovyTestCase and ran them all as a batch, they all passed. I took that ugly configuration code out of the setUp() method and ran it again, and they all passed. Problem solved (thanks, Eric!).Jeffrey Eriksonhttp://www.blogger.com/profile/05123996612107368819noreply@blogger.com1tag:blogger.com,1999:blog-6974519331013632764.post-27689241211207935982009-08-29T11:43:00.005-04:002009-09-01T12:07:51.645-04:00Groovy RESTClient, HTTPBuilder, and PUT responses with no bodyIn working with a RESTful web service that allows PUT requests to upload files, I came across an slight annoyance with the put() convenience method in the Groovy <a href="http://groovy.codehaus.org/modules/http-builder/doc/rest.html">RESTClient</a>. Up until now, I've been absolutely amazed with how easy RESTClient makes my life in working with RESTful web services, and I'll continue to use it in doing REST development. However, in this one case, RESTClient wouldn't work nicely for me.<br /><br />Here's the scenario: I upload a zip file to the service so that it can use the data in that file to populate some things (see my post <a href="http://agileice.blogspot.com/2009/08/groovy-restclient-and-putting-zip-files.html">Groovy, RESTClient, and PUTting zip files</a> for one way to get RESTClient to handle zip files). I watch the log on the server and see that it's handling that file just fine; however, my Groovy script errors out! What's going on?<br /><br />Here's what the Groovy code looked like at this point:<br /><pre class="brush: groovy"><br />def file = new File("data_file.zip")<br />def rest = new RESTClient( 'http://localhost:8080/server/rest/' )<br />rest.encoder.'application/zip' = { ... handle zip files ... }<br />rest.put( path: "data/data_file.zip", body: file, requestContentType: 'application/zip' )<br /></pre><br /><br />It turns out that the RESTful service, once it gets the file, just sends back an HTTP "201 Created" response code. No body to the response at all because, really, there's none needed. However, by default, the RESTClient put() method wants a response body to parse and return, so it throws a NullPointerException when it tries to parse that "nothing".<br /><br />Since I didn't see a way of telling RESTClient not to expect a response body, I could have just lived with the exception, catching it and moving along. But the exception was being thrown before the response object was passed back, I couldn't even check the status of my request to see if the request was successful or if there were problems. Fortunately, RESTClient is really just a set of convenience wrappers around the main <a href="http://groovy.codehaus.org/modules/http-builder/doc/index.html">HTTPBuilder</a>, so I was able to implement my request using HTTPBuilder. <br /><br />HTTPBuilder has the nice feature of allowing you to assign different response handlers to different HTTP response codes, so I could basically tell it not to bother trying to parse '201' responses and just print a "success" message. Here's how I ended up setting up the PUT request using HTTPBuilder:<br /><pre class="brush: groovy"><br />import groovyx.net.http.HTTPBuilder<br />import groovyx.net.http.Method<br /><br />def file = new File("data_file.zip")<br /><br />def http = new HTTPBuilder('http://localhost:8080/server/rest/')<br />http.encoder.'application/zip' = { ... handle zip file ... }<br /><br />http.request(Method.PUT) { req -><br /> uri.path = 'data/data_file.zip'<br /> send("application/zip", file)<br /><br /> response.'201' = { resp -><br /> println resp.status<br /> }<br /><br /> response.success = { resp, object -><br /> println resp.status<br /> }<br /><br /> response.failure = { resp -><br /> println resp.statusLine<br /> }<br />}<br /></pre><br /><br />Of course, we could do a lot more with the response objects, but at this point, all we want to know is whether our request failed or succeeded, without having to worry about a response body. While it's definitely not as convenient as RESTClient, with the HTTPBuilder implementation in place, the file uploaded just fine, and there were no errors on the Groovy end of things.Jeffrey Eriksonhttp://www.blogger.com/profile/05123996612107368819noreply@blogger.com4tag:blogger.com,1999:blog-6974519331013632764.post-28136742271767951392009-08-29T11:21:00.005-04:002009-08-31T07:58:53.812-04:00Groovy RESTClient and PUTting zip filesI'm currently working with a RESTful web service that requires a client to upload a zip file with a content-type of 'application/zip'. Since we're using more and more Groovy in our shop, we initially tried to PUT the zip file using Groovy's <a href="http://groovy.codehaus.org/modules/http-builder/doc/index.html">HTTPBuilder/RESTClient</a>. Our initial attempt looked like this:<br /><pre class="brush: groovy"><br />def file = new File("data_file.zip")<br />def rest = new RESTClient( 'http://localhost:8080/server/rest/' )<br />rest.put( path: "data/data_file.zip", body: file, requestContentType: 'application/zip' )<br /></pre><br /><br />When we first tried to run it, we kept getting NullPointerExceptions from RESTClient/HTTPBuilder trying to set the body of the request. Digging into the code, it looked like, by default, HTTPBuilder doesn't know how to handle zip files. It can do other kinds of binary encoding, but the content-type needs to be 'application/octet-stream', something the server we were using doesn't understand.<br /><br />What we had to do was actually create our own encoding process and register that with the RESTClient. Using the HTTPBuilder EncoderRegistry.encodeStream() method (which returns <a href="http://hc.apache.org/httpcomponents-core/httpcore/apidocs/org/apache/http/entity/InputStreamEntity.html">InputStreamEntity</a> instances of <a href="http://hc.apache.org/httpcomponents-core/httpcore/apidocs/org/apache/http/HttpEntity.html">org.apache.http.HttpEntity</a>) as a starting point, here's what we came up with:<br /><pre class="brush: groovy"><br />/**<br /> * Request encoder for a zip file.<br /> * @param data a File object pointing to a Zip file on the file system<br /> * @return an {@link FileEntity} encapsulating this request data<br /> * @throws UnsupportedEncodingException<br /> */<br />def encodeZipFile( Object data ) throws UnsupportedEncodingException {<br /> if ( data instanceof File ) {<br /> def entity = new org.apache.http.entity.FileEntity( (File) data, "application/zip" );<br /> entity.setContentType( "application/zip" );<br /> return entity<br /> } else {<br /> throw new IllegalArgumentException( <br /> "Don't know how to encode ${data.class.name} as a zip file" );<br /> }<br />}<br /></pre><br /><br />Basically, what we're doing is, instead of returning an InputStreamEntity, we return a FileEntity and set it's content-type to 'application/zip'. Of course, in the above code, we could do more strenuous checking on the data to make sure that it's actually a zip file and such. As well, we could probably expand it to handle other specific binary types. But in this case, we knew we were getting a zip file and nothing else, so <a href="http://en.wikipedia.org/wiki/You_Ain%27t_Gonna_Need_It">YAGNI</a>.<br /><br />Once we had that method in place, all we needed to do was register it with HTTPBuilder/RESTClient. HTTPBuilder/RESTClient allows access to its encoders Map, and its propertyMissing() setter implementation automatically registers an encoder to that Map, so it was easy to attach our zip file encoder to our client object:<br /><pre class="brush: groovy"><br />rest.encoder.'application/zip' = this.&encodeZipFile<br /></pre><br /><br />With that in place, uploading the zip file to the RESTful web service worked. Our final code looked something like this:<br /><pre class="brush: groovy"><br />def file = new File("data_file.zip")<br /><br />def rest = new RESTClient( 'http://localhost:8080/server/rest/' )<br />rest.encoder.'application/zip' = this.&encodeZipFile<br />rest.put( path: "data/data_file.zip", body: file, requestContentType: 'application/zip' )<br /><br />def encodeZipFile( Object data ) throws UnsupportedEncodingException {<br /> if ( data instanceof File ) {<br /> def entity = new FileEntity( (File) data, "application/zip" );<br /> entity.setContentType( "application/zip" );<br /> return entity<br /> } else {<br /> throw new IllegalArgumentException( <br /> "Don't know how to encode ${data.class.name} as a zip file" );<br /> }<br />}<br /></pre>Jeffrey Eriksonhttp://www.blogger.com/profile/05123996612107368819noreply@blogger.com2tag:blogger.com,1999:blog-6974519331013632764.post-47525527258997072002009-08-07T09:34:00.004-04:002009-08-31T07:59:44.447-04:00Grails, JSecurity, and View URL Mapping in JBossI've been trying to get my app created in Grails 1.1.1 using the JSecurity plugin to deploy in JBoss 4.2.3.GA. Everything worked fine when I test it using 'grails run-app', but when I deployed my WAR file to JBoss, I got an IllegalStateException any time I tried to access something where I mapped a URL to a view in my UrlMappings.groovy file like this:<br /><pre class="brush: groovy"><br />"/"(view:"index")<br />"500"(view:"error")<br /></pre><br /><br />It turns out that there's a bug open in the JSecurity plugin: <a href="https://jira.codehaus.org/browse/GRAILSPLUGINS-1117">GRAILSPLUGINS-1117</a>. Basically, there's not much explanation as to why, but there is a work-around. Instead of mapping to a view in the UrlMappings file, you map to a controller and action. In the case of the error view, it would look something like this:<br /><pre class="brush: groovy"><br />"500"(controller:"errors", action:"serverError")<br /></pre><br />However, there isn't a nice way (that I've found, at least) to map the default "index" view. Instead, you'll either have to create a custom "home" controller that forwards to your generic index page, or map the "/" URL to one of your existing controller actions. In the case of my application, since the main entry point will eventually be through one of the existing controllers anyway, I ended up mapping "/" to that:<br /><pre class="brush: groovy"><br />"/"(controller:"entryController", action: "list")<br /></pre><br /><br />With those changes, the app works just fine under JBoss 4.2.3.GA. The JSecurity plugin bug is currently marked as major, so I hope at least it's getting some attention and will be fixed in the near future.Jeffrey Eriksonhttp://www.blogger.com/profile/05123996612107368819noreply@blogger.com0tag:blogger.com,1999:blog-6974519331013632764.post-60003154285038356832009-04-29T08:32:00.006-04:002009-04-29T08:44:31.196-04:00Enabling the "Accept" header for Grails/RESTI've been trying to implement a RESTful web service using Grails, following along a number of articles on the web for examples (Scott Davis has a particularly good one here: <a href="http://www.ibm.com/developerworks/java/library/j-grails09168/index.html">RESTful Grails</a>). To get back XML from a Grails app that will be serving up both HTML and XML, I was setting the HTTP "Accept" header, then using content negotiation in my controller classes to determine what to send back to the client. For some reason, though, my app kept spitting back HTML even when I was specifically requesting XML.<br /><br />Well, it turns out that, according to this <a href="http://jira.codehaus.org/browse/GRAILS-3792">Jira post</a>, as of Grails 1.1, using the Accept header is disabled by default. To enable it, open up the Grails app's Config.groovy file (grails-app/conf/Config.groovy), and set "grails.mime.use.accept.header" to true.<br /><br />Once I got that figured out, everything is running really smoothly.Jeffrey Eriksonhttp://www.blogger.com/profile/05123996612107368819noreply@blogger.com0tag:blogger.com,1999:blog-6974519331013632764.post-18748394916387274792009-04-28T09:29:00.007-04:002009-04-28T09:42:21.156-04:00Playing a nicer beep in Gnome terminal under UbuntuWith all the tab-completion and such that I do at the command line, sometimes that system beep can get really annoying. I like to have audio feedback when I'm working, so I didn't want to disable the beep completely, but I did want something that wasn't quite so harsh. I searched around for a while in the preferences to see if I could change things to play a nicer sound file instead of the speaker's beep, but it doesn't look like that's available as an option. Searching the web, I found this post at tjworld.net, which got my system playing the sound file I wanted: <a href="http://tjworld.net/wiki/Linux/Ubuntu/XandGnomeSystemBeepWithAudioFile">XandGnomeSystemBeepWithAudioFile</a>. (Note: there's a misspelling for the xkbevd config file name in that post; it's actually "xkbevd.cf".)<br /><br />While that finally got a sound file playing instead of the beep in other apps, in the Gnome terminal, it played both the sound file *and* the system beep . . . even more annoying :). In the end, here's what I had to do to get *only* the sound file playing as the beep in the Terminal:<br /><br />First, in the System->Preferences->Sound preference setter, go to the System Beep tab, and de-select "Enable System Beep".<br /><br />Next, in the Gnome terminal Edit->Profiles menu, select the profile you're using, then on the Edit->General tab make sure "Terminal bell" is selected.<br /><br />So, you have to *disable* the system beep in the global settings, then *enable* it in the terminal settings.Jeffrey Eriksonhttp://www.blogger.com/profile/05123996612107368819noreply@blogger.com0tag:blogger.com,1999:blog-6974519331013632764.post-82408677223520696032009-04-01T12:22:00.008-04:002009-08-31T08:00:44.777-04:00Accessing the Maven runtime classpath in a Groovy scriptLately, I've been involved in converting a good portion of our source tree that's currently built with Ant over to building with Maven. We have a number of Groovy scripts that we use throughout our build, and I've had great success with the <a href="http://groovy.codehaus.org/GMaven">GMaven plugin</a> to get things working. I ran into one snag, though, when I was trying to run one of our Groovy scripts that generates Textile wiki markup via a custom Javadoc doclet.<br /><br />To get the doclet to run, I needed to supply the path/classpath where it could be found, and since the doclet is built during the project's compile phase, I needed access to the Maven runtime classpath to get the documentation built (admittedly, it shouldn't be part of the "project", but if it were, instead, an outside dependency, I'd still need access to the Maven compile classpath, so the problem is pretty much the same). The Maven AntRun plugin provides a nice reference to that classpath via the "maven.runtime.classpath" property that can be accessed in the Maven Ant targets, so I was hoping that GMaven would provide the same sort of thing, especially since they give good access to an AntBuilder automatically.<br /><br />At this point, though, they don't, and I really didn't want to resort to embedding Ant in our Maven build just to run a Groovy script (for a number of reasons). After a good amount of experimentation and searching, I found <a href="http://jira.codehaus.org/browse/MGROOVY-189?focusedCommentId=167327&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_167327">this GMaven Jira entry</a> that gives a little bit of guidance for how a GMaven Mojo might build those same kind of classpath references. It didn't really address how to get those classpaths in an executed script, though, but Groovy is Groovy, so I figured it could be done :). Experimenting with what's laid out there and digging into the Ant API docs, here's a what I came up with:<br /><br />First, of course, you need to get GMaven to run during your build. The <a href="http://groovy.codehaus.org/GMaven+-+Executing+Groovy+Code">GMaven documentation</a> is great for showing how to edit your POM to call a Groovy script during the build. Next, in the Groovy script you want to run, you need to import org.apache.tools.ant.types.Path, and instantiate a new Path object (before you want to reference the path, naturally). When you make a new Path object, you need to give it a reference to the Ant Project to which it belongs, and, as I mentioned, GMaven gives you reference to an AntBuilder (via the "ant" default variable) where you can get that project. The code so far might look like this:<br /><pre class="brush: groovy"><br />import org.apache.tools.ant.types.Path<br /><br />Path runtimePath = new Path(ant.antProject)<br /></pre><br /><br />Once you have that Path object, you need to tell it what its path should look like. Since we're trying to set the runtime classpath Maven builds, we need to find out what JAR files and compiled classes are in Maven's runtime classpath. Fortunately, GMaven also gives us access to a MavenProject object by default, referenced by the default variable "project" in the script. We can build up our path, then, by joining the different pieces of the MavenProject's runtimeClasspathElements and setting that to our Path's path:<br /><pre class="brush: groovy"><br />runtimePath.path = project.runtimeClasspathElements.join(File.pathSeparator)<br /></pre><br /><br />Finally, in order to reference that path by name in our script where we need it, we have to add a reference to it in our Ant Project object:<br /><pre class="brush: groovy"><br />ant.antProject.addReference('runtime.classpath',runtimePath)<br /></pre><br /><br />The final code for building the runtime classpath looks like this:<br /><pre class="brush: groovy"><br />import org.apache.tools.ant.types.Path<br /><br />Path runtimePath = new Path(ant.antProject)<br />runtimePath.path = project.runtimeClasspathElements.join(File.pathSeparator)<br />ant.antProject.addReference('runtime.classpath',runtimePath)<br /></pre><br /><br />Once we have that defined, we can reference it in the script just like we would any other Ant reference. For example, in the project I'm working on, I need to supply a path reference to the Ant Javadoc task. Since I named the path above "runtime.classpath", I set up my Javadoc task call in the Groovy script like this:<br /><pre class="brush: groovy"><br />ant.javadoc(... docletpathref: 'runtime.classpath' ...) {<br /> ... more Groovy code to execute ...<br />}<br /></pre><br /><br />While it would definitely be easier if GMaven provided these classpaths out of the box, it's actually not that hard to build them up in the script when you need them. By the way, you can do the same thing with the Maven compile classpath: instead of referencing "project.runtimeClasspathElements" when building the path, you use "project.compileClasspathElements". If you need the plugin classpath, the process is a little more complex, but if you get what's going on above, then you can probably follow the example in the <a href="http://jira.codehaus.org/browse/MGROOVY-189?focusedCommentId=167327&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_167327">GMaven Jira post</a> to build the plugin classpath.Jeffrey Eriksonhttp://www.blogger.com/profile/05123996612107368819noreply@blogger.com0tag:blogger.com,1999:blog-6974519331013632764.post-65517277498060685122008-11-26T12:11:00.005-05:002008-11-26T12:49:42.304-05:00Accessing Subversion via SSH on a non-standard portThis may be common knowledge, but it took me a few minutes to figure out and I didn't want to have to spend a few minutes again in the future when I forget how to do this months down the line :).<br /><br />There are two, somewhat easy ways to configure different options to SSH for SVN. The first option lets you make the options specific to SVN access; in other words, the options you use to access the SSH server will only affect SVN access. The second lets you make those options standard across any SSH access you make to that target server.<br /><br />Let's say I have a server called "reposerver" that has SSH listening on port 12345. The SVN repository there is under "/var/svn/repos" and contains a project called "test-project". To check out that project via SVN+SSH, here's what you need to know:<br /><br /><span style="font-weight:bold;">Option one:</span><br /><br />Basically, in your home directory (on a Linux system), there's a file <span style="font-style:italic;">.subversion/config</span>. In that config file, there's a section called <span style="font-style:italic;">[tunnels]</span>. Edit that section so that it has an entry like this:<br /><pre><br />[tunnels]<br />reposerver = $SVN_SSH ssh -p 12345<br /></pre><br />The "reposerver" part could be anything; I just named it the name of the server so it'd be easy to remember when I have to use it in a later step. What the rest of that entry does is call your SSH command with any of the normal SSH options, so if there are other options you'd normally use, you can also put them there.<br /><br />Finally, when you're done with that file, save it. Then attempt to check out a project from your SVN server. Normally, you'd type "svn+ssh" as the protocol portion of the URL. But this time, you'll use the name of the "tunnel" you defined in your SVN config file:<br /><pre><br />svn co svn+reposerver://reposerver/var/svn/repos/test-project<br /></pre><br /><br />It would definitely be nice if SVN supported passing ports along in the normal way URLs do (ie. http://server:port), but at least this gives you some level of configurability with different options in accessing the repository. In fact, you could, for example, use a different SSH implementation, or RSH, or whatever you wanted to do.<br /><br /><br /><span style="font-weight:bold;">Option two:</span><br /><br />You can edit the <span style="font-style:italic;">.ssh/config</span> file in your home directory. Basically, you'd add a "Host" entry, and beneath that put any options you want to use whenever you access that host via SSH. For our example, the entry might look like this:<br /><pre><br />Host reposerver<br /> Port 12345<br /></pre><br />Once you add the options you want to your .ssh/config file (check out <a href="http://www.ssh.com/support/documentation/online/ssh/adminguide-zos/54/ssh2_config.html#MAN-SSH2CONFIG">the SSH2 client config man page</a> for other options and more information), when you attempt to access SVN on the SSH server, those options will be passed on, too. So our checkout command would look like this:<br /><pre><br />svn co svn+ssh://reposerver/var/svn/repos/test-project<br /></pre><br />Note, this time we're using the normal "svn+ssh" as the protocol; you don't need to worry about any "tunnel" names or anything like that, and that's the advantage to this approach: you don't need to remember anything out of the ordinary. However, if somehow you want different options for SVN SSH access and regular SSH access, then option one above will probably be better for you.Jeffrey Eriksonhttp://www.blogger.com/profile/05123996612107368819noreply@blogger.com1tag:blogger.com,1999:blog-6974519331013632764.post-63996787645948000792008-10-11T03:55:00.011-04:002009-08-31T08:06:00.461-04:00Using Groovy to connect to GMailLately, I've been working on a project where I want to allow someone (namely, my wife) to email to-do items to my GMail account, which an automated process would then read, find the relevant items, then add them to this really useful GTD app I've been using, <a href="http://www.rousette.org.uk/projects/">Tracks</a>. The language I've been using over the last year or so to automate things like this is Groovy, and Groovy actually makes a task like this fairly easy<br /><br />GMail also has made it easier if you want to automate some of your mail handling like I do: they provide access via regular POP3 and IMAP. IMAP is particularly useful because, if you have created labels in GMail (and I only know one person who hasn't ;)), GMail IMAP will treat those labels as IMAP folders. So there are basically two parts to this task: actually connecting to the GMail IMAP server, then interacting with the labels/folders in your account. <br /><br /><span style="font-weight:bold;">Connecting to GMail</span><br /><br />GMail requires you to use SSL to connect to their servers, so the first thing I had to do was get GMail's certificate into a Java keystore. Based in part on the instructions in <a href="http://blog.vinceliu.com/2007/11/changing-gmail-ssl-certificate.html">this blog post by Vincent Liu</a>, here's what I did:<br /><br />First, I connected to GMail's IMAP service with openssl:<br /><pre class="brush: shell"><br />openssl s_client -connect imap.gmail.com:993 -showcert<br /></pre><br /><br />From the output of that session, I copied the lines from "-----BEGIN CERTIFICATE-----" to "-----END CERTIFICATE-----" (inclusive), to a text editor and saved it as the file gmail.pem. To make the certificate usable by Groovy, I then used openssl again to convert the PEM file to a DER format that I could import via Java's keytool utility.<br /><pre class="brush: shell"><br />openssl x509 -in gmail.pem -inform PEM -out gmail.der -outform DER<br /></pre><br /><br />Just to make sure things were on the up-and-up, I viewed the resulting certificate:<br /><pre class="brush: shell"><br />keytool -printcert -file gmail.der<br /></pre><br />Then I imported the certificate into my keystore:<br /><pre class="brush: shell"><br />keytool -import -alias gmail.imap -file gmail.der<br /></pre><br /><br /><span style="font-weight:bold;">Interacting with GMail</span><br /><br />Once the certificate was taken care of, I could get down to actually connecting to GMail with Groovy. One of the best things about Groovy is that it can make use of all the Java libraries that already exist for doing things like connecting to mail servers. I used the <a href="http://java.sun.com/products/javamail/">JavaMail</a> libraries to do the real work of connecting to GMail, and there is some good documentation out there on how to use it. Here are some of the basics, though:<br /><br />First off, you need to import the JavaMail classes (as well as java.util.Properties for initiating a JavaMail connection):<br /><pre class="brush: groovy"><br />import javax.mail.*<br />import java.util.Properties<br /></pre><br />and then set some properties for your mail Session:<br /><pre class="brush: groovy"><br />String gmailServer = "imap.gmail.com"<br />int gmailPort = 993<br /><br />Properties props = new Properties();<br />props.setProperty("mail.store.protocol", "imaps");<br />props.setProperty("mail.imaps.host", gmailServer);<br />props.setProperty("mail.imaps.port", gmailPort.toString());<br /></pre><br />Note that the "mail.store.protocol" property is "imaps" NOT plain "imap". JavaMail added SSL support to all protocols in version 1.3.2.<br /><br />Once you have those properties set, you can create a Session and connect to the GMail IMAP server (the Store, in JavaMail terms) via IMAPS:<br /><pre class="brush: groovy"><br />def session = Session.getDefaultInstance(props,null)<br />def store = session.getStore("imaps")<br />store.connect(server, user, password)<br /></pre><br /><br />With the connection to the Store, the next thing you probably want to do is see what's there. As I mentioned, GMail treats all your labels as IMAP folders. You can list the folders that are available, and then interact with the messages in whatever folder you're interested in:<br /><pre class="brush: groovy"><br />store.defaultFolder.list().each { folder -><br /> println folder.name<br />}<br /><br />def inboxFolder = "INBOX"<br />def folder = store.getFolder(inboxFolder)<br />folder.open(Folder.READ_ONLY)<br />folder.messages.each { msg -><br /> println "Subject: ${msg.subject}"<br /> println "Sent on: ${msg.sentDate}"<br /> println "From: ${msg.from}"<br /> println "Content: ${msg.content}"<br /> println "----------------------\n"<br />}<br /></pre><br /><br />Once you're connected like this, you can interact with GMail as if it were any regular IMAP server, so check out the <a href="http://java.sun.com/products/javamail/javadocs/index.html">JavaMail API</a> to see all the ways you can interact with a mail server.Jeffrey Eriksonhttp://www.blogger.com/profile/05123996612107368819noreply@blogger.com2tag:blogger.com,1999:blog-6974519331013632764.post-49215543459391581482008-09-22T21:42:00.008-04:002009-08-31T08:09:15.334-04:00Adding HTTP Basic Authorization to GroovyHTTPA while back, I discovered a great little Groovy utility by Tony Landis called <a href="http://www.tonylandis.com/code-projects/groovy-http-post-get-class.html">GroovyHTTP</a> which allows you to generate web requests in Groovy. I've used it with great success on a number of projects.<br /><br />Lately, I've been playing with a neat GTD web app named <a href="http://www.rousette.org.uk/projects/">Tracks</a>, which has a nice RESTful API for adding tasks, etc. To interact with the application via the API, though, you need to be able to authenticate via HTTP Basic authentication, and GroovyHTTP doesn't seem to support that. Since I really want to interact with Tracks on my internal network with Groovy, I've taken a stab at adding HTTP Basic authentication to GroovyHTTP. Of course, I realize that HTTP Basic is not the most secure authentication method (that's an understatement!), but when you need it, you need it.<br /><br />It really boils down to adding one method to set the user and login on the GroovyHTTP object, then adding a Base64-encoded authorization string to the HTTP request headers. The extra header line ends up looking like this (for the user/password "Aladdin/open sesame"):<br /><pre class="brush: plain"><br />Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==<br /></pre><br /><br />To use the modified GroovyHTTP class to access a URL protected by Basic authentication, you can do something like this:<br /><pre class="brush: groovy"><br /> def h = new GroovyHTTP(protectedUrl)<br /> h.setMethod('POST')<br /> h.setAuthorization(login, password)<br /> h.setParam('p1', p1)<br /> h.setParam('p2', p2)<br /></pre><br /><br />Since I can't find any contact information for Tony Landis on his site, I figured I'd post the Groovy code here since he's released it under the BSD license. The Groovy class is available here: <a href="http://docs.google.com/Doc?id=dgkjd59b_23chm7cfdh">GroovyHTTP with HTTP Basic Authentication</a>. NOTE: It looks like Google Docs has messed up the formatting in the Groovy class. When I get some time, I'll try to neaten it up.Jeffrey Eriksonhttp://www.blogger.com/profile/05123996612107368819noreply@blogger.com2tag:blogger.com,1999:blog-6974519331013632764.post-10454570092404219372008-09-12T09:55:00.016-04:002009-08-31T08:10:38.634-04:00Rendering complex collections as JSON in GrailsSo I have a set of somewhat complex objects I need to render as JSON in Grails for some AJAX calls. Let's say I have an array of "Foo" objects, each of which contains a name and an array of "Bar" objects, each of which have a name and a location.<br /><br />I want the JSON to look something like this (granted, there are a number of ways I could probably use simpler data structures with more frequent AJAX calls, but I'm trying to make as few trips to the server as possible) :<br /><pre class="brush: groovy"><br />{"foos":<br /> [<br /> {<br /> "fooName":"fooOne",<br /> "bars":[<br /> {"barName":"barOne","location":"here"},<br /> {"barName":"barTwo","location":"there"},<br /> {"barName":"barThree","location":"everywhere"}<br /> ]<br /> },<br /> {<br /> "fooName":"fooTwo",<br /> "bars":[<br /> {"barName":"barFour","location":"Istanbul"},<br /> {"barName":"barFive","location":"Constantiople"},<br /> {"barName":"barSix","location":"Nobody's Business"}<br /> ]<br /> }<br /> ]<br />}<br /></pre><br />I tried for a while to get this to render using Grails JSONBuilder, but to no avail: the secondary arrays kept being built outside the Foo objects. Eventually, I came across this really helpful post: <a href="http://memo.feedlr.com/?p=6">Mini-Guide to rendering JSON with Grails</a> that pretty much described the things I had tried and the problems I encountered. The post suggested trying the JSON converter that's bundled with Grails and gave a fairly simple example of how to use it.<br /><br />The JSON I wanted to build was a bit more complex than the example, though, so I went searching for more examples of how to use the JSON converter. In the examples I found, most of the structures didn't go as deeply as the one I wanted; most of them just included a list at the top level of the structure, using the Grails "list" method (e.g. Books.list(params), which would get you the listing of books with the param IDs). I needed to go one step deeper, so I thought I'd see if Grails would automatically recurse the Lists in my objects. No such luck: when I tried rendering like this "render foos as JSON", the first-level items rendered correctly, but the array of Bars was empty.<br /><br />Finally, I just decided to try constructing the data structures myself since maybe the JSON converter had trouble navigating object graphs but not basic collections. Since Javascript doesn't really differentiate between Objects and Maps (which is basically how JSON works), I created a Map for each Bar, put them into an array which then went into a Foo Map containing the attributes for the Foo. Finally, I created an array of the Foo Maps, which I then rendered using the JSON converter.<br /><br />That actually worked! The downside, though, is that this is pretty fragile: if the data I want to return from the Foo or Bar objects changes, I have to change how the containers are rendered. <br /><br />I don't know how much of what I encountered in JSONBuilder or the JSON converter is by design (maybe trying to force less complex data structures), but it certainly would be helpful to be able to create these kinds of arbitrarily complex structures based on the objects themselves rather than having to create our own containers. I'll have to see if anyone is already working on that.<br /><br />Here's the final code I ended up with (it's probably not idiomatic Groovy, but I'm more familiar with Java, so it was quick):<br /><pre class="brush: groovy"><br /> import grails.converters.JSON<br /> . . .<br /> def getJson = {<br /> def fooList = new ArrayList()<br /> data.foos.each { foo -><br /> <br /> def fooMap = new HashMap()<br /> fooMap.put("fooName", foo.fooName)<br /> <br /> // see what bars this foo has<br /> def bars = new ArrayList()<br /> foo.bars.each { bar -><br /> def barMap = new HashMap()<br /> barMap.put("barName", bar.barName)<br /> barMap.put("location", bar.location)<br /> bars.add(barMap)<br /> }<br /> fooMap.put("bars", bars)<br /><br /> fooList.add(fooMap)<br /> }<br /><br /> def output = [<br /> foos: fooList<br /> ]<br /><br /> render output as JSON<br /> }<br /></pre>Jeffrey Eriksonhttp://www.blogger.com/profile/05123996612107368819noreply@blogger.com1tag:blogger.com,1999:blog-6974519331013632764.post-57224579649173880812008-09-10T19:58:00.006-04:002008-09-11T10:35:30.545-04:00Rich Web Experience 2008: the Nate Schutta SessionsThinking back on the RWE 2008 last week, I realized there were a number of sessions that really stood out as being well presented and extremely informative. In particular, the sessions by Nate Schutta (check out his blog at <a href="http://ntschutta.com/jat">http://ntschutta/jat</a>) were among some of the best I've seen. They were all clear, well-thought out, in-depth, and engaging. A number of his presentations were introductions to various popular Javascript libraries like Prototype, YUI, and Dojo. These were particularly good because he showed not only why the libraries were useful but also how to use them. He didn't leave it at theory or sales pitch, though; in each of his script library presentations, he coded a number of examples using the libraries in question. And here's the best part: in each presentation, he built the same type of applications (a simple PIM app, showing how to use a date picker, etc) but using the library under discussion. It made for a good comparison of the strengths and APIs of each library. Also, he showed in his examples how the different libraries could actually work together, building on the strengths of each. All in all, the content of his presentations was excellent.<br /><br />In addition to the excellent content, though, his method of presentation was right up my alley. He did what I consider the best thing to do in using slide presentations: he used the slides to initiate discussion rather than regurgitating the points from the slides. Some presenters tend to read their slides and that's their presentation. That gets old really quickly. As well, I remember one time when I was in the Army and giving a briefing to a warrant officer being told that people can either read your slides or listen to you, not do both at the same time. Nate kept his slides clean and simple, usually just a few words or phrases per slide, which allowed him to emphasize his points and guide his discussion of the topic without the listeners getting distracted by a lot of visual noise on the screen. He actually did something really interesting, too, for his final presentation of the weekend (A Software Engineer's Guide to Usability): he had two different slide decks. The first contained his simple slides described above, and the other had more content grouped in bullet points and images. I guess people had complained that the slides didn't make good take-aways (which is probably true, unless you're an extremely thorough note taker) since they were more for guiding the discussion than posting information. I think it was a good tactic. in fact, I actually found myself referring to his "note slides" earlier today when writing up some notes for some of my colleagues.<br /><br />I know some people don't like this form of presentation. In environments like this weekend, I tend to be a more audio learner, so Nate's presentation style really worked for me. But for people who are more visually oriented and who want to get their information mainly from the screen, that "simple" form of presentation might cause problems. But overall, I'd say his presentations, from my point of view, were among the best there, and actually were among the best I've seen in attending other NFJS events, too.Jeffrey Eriksonhttp://www.blogger.com/profile/05123996612107368819noreply@blogger.com2tag:blogger.com,1999:blog-6974519331013632764.post-88811283532346373232008-09-08T19:44:00.004-04:002008-09-08T20:17:56.746-04:00Tracking visitor statistics on a Blogger blog<span class="Apple-style-span" style="font-family: arial;">So I wanted to track various statistics on who's visiting my blog, and it didn't appear that there was any sort of tool available via Blogger. So what I ended up doing is hooking my blog into Google Analytics.</span><div><span class="Apple-style-span" style="font-family: arial;"><br /></span></div><div><span class="Apple-style-span" style="font-family: arial;">First, I had to sign up for a free Google Analytics account. When it asked for the URL of my site, I put in the URL to this blog (http://agileice.blogspot.com) and gave the new account a name. After putting in my contact information and agreeing to the terms of service, Google gave me some tracking code that I needed to add to my blog site.</span></div><div><span class="Apple-style-span" style="font-family: arial;"><br /></span></div><div><span class="Apple-style-span" style="font-family: arial;">To add that code to my blog, I logged into my blog and clicked the "Customize" link at the top of the page. From the "Layout" tag, I clicked the "Edit HTML" link which brings up the actual HTML template for the blog page. I scrolled down to the bottom of the HTML, and inserted the code from the Analytics page right above the closing </body> tag. That's really all there was to it. NOTE: the code *has* to go at the bottom of your page.</span></div><div><span class="Apple-style-span" style="font-family: arial;"><br /></span></div><div><span class="Apple-style-span" style="font-family: arial;">Once the code was installed, I logged in to my Google Analytics account. In the stats table for my blog, the cell at the far right was a different color and said "Tracking Unknown": Google Analytics hadn't yet communicated with the site. I clicked the "Check Status" link and the cell changed to read "Tracking Installed". That's pretty much all there is to it.</span></div><div><span class="Apple-style-span" style="font-family: arial;"><br /></span></div><div><span class="Apple-style-span" style="font-family: arial;">Now I can easily check the visitor statistics for my blog just by logging in to my Google Analytics account. I can get reports on how many visitors I've had, where they're from, how many hits I've gotten over time, and all sorts of other data views. There are even tools that I can install on the blog that will show the stats updated hourly (though I think I'd rather just keep it on the Analytics site).</span></div>Jeffrey Eriksonhttp://www.blogger.com/profile/05123996612107368819noreply@blogger.com2tag:blogger.com,1999:blog-6974519331013632764.post-65696079974937606462008-09-07T15:00:00.000-04:002008-09-08T08:21:55.583-04:00Registering a domain using Google Apps, but hosting "www" yourselfSo I registered a new domain today: agileice.com. In the past, I've registered a few domains (eriksontech.net and eriksonweb.com) with a couple other companies (one with a hosting package that expired a couple years ago and one with Yahoo!). They weren't bad experiences, but I decided to go with Google's partners this time, partly because of Google Apps. I like the idea of not having to mess with email at the domain and being able to use GMail's familiar interface for the mail that goes to that address. Initially, though, they registered the "www" alias back to the "start" pages they set up for me, which meant that the address in the address bar of the browser went from the simple "http://www.agileice.com" through what appeared to be a couple forwards to end up as "http://partnerpage.google.com/agileice.com". If I do end up doing business on this domain, I don't want potential customers going to an address like that. I also wanted to be able to control a number of other services and things behind www.agileice.com (SSH, in particular).<div><br /></div><div>Here's what I ended up doing: Once you log into the domain you registered with Google Apps (by going to https://www.google.com/a/[domain name here]), you can go to the "Domain Settings" then the "Domain Names" section. Once you're there, you can get to the actual domain registrar's site (Google partners with a couple other companies to register the domain name; it doesn't register the name itself) by clicking the "Advanced DNS Settings" link. In my case, I registered the address with eNom, who has a fairly straightforward interface for managing the various parts of the DNS entries. In my case, I needed to edit the "Host Records" section where wanted to forward the "www" host to my actual IP address.</div><div><br /></div><div>In the "Host Records" section, there are actually a few types of entries; the two types that really mattered in this case are "A" and "CNAME". An "A" entry stands for an actual IP address; a "CNAME" entry is more of an alias, forwarding the host to the "named" address in the entry. When I registered with Google Apps, eNom automatically filled in a number of entries for me, setting a few "A" entries to what I assume are Google's IP addresses, and then aliasing a number of other services (Mail, Calendar, etc) to the Google services address "ghs.google.com". All I ended up doing was changing the "www" entry (which Google had set as a "CNAME" entry) to an "A" entry pointing at the static IP address I have through my ISP.</div><div><br /></div><div>It took a little while for the changes to propagate through the net, but now when someone goes to www.agileice.com, they'll actually get the pages I'm hosting here rather than being forwarded to the Google pages (or they will once I actually start hosting some pages here ;)). And things like Google Mail for agileice.com still work.</div>Jeffrey Eriksonhttp://www.blogger.com/profile/05123996612107368819noreply@blogger.com0tag:blogger.com,1999:blog-6974519331013632764.post-50526251410268154142008-09-06T17:30:00.004-04:002008-09-08T17:32:31.398-04:00Thoughts from RWE 2008 final keynote<span style="font-family: arial;font-family:lucida grande;"><span class="Apple-style-span">Just got finished up with a Rich Web Experience conference today, where the final *scheduled* keynote speaker--Jared Richardson--made some very good points about getting your ideas out there both for earning some name recognition and for being able to get to them yourself some time in the future when you may need them. He suggested blogging (and I wonder just how many blogs are getting started up right now :)) as a great way to start pushing your information out there.<br /><br />One of the things he suggested is blogging anything that's taken you more than 10 or 15 minutes to figure out. The idea is that if it took you some time to figure out, it'll take someone else some time to figure out, and by posting it on your blog, you'll have access in to it in the future and, if people find it useful, then you'll be getting some exposure. Enough exposure, and it might lead to other things.<br /><br />He also suggested getting involved in open source projects, not just in starting them up or becoming a leader or main contributor from the get go, but starting small. Pick a bug and fix it. Or, even better, do something no one else wants to do, like write documentation. It's a good way to get involved and to start getting your name out there.<br /><br />The other interesting thing he mentioned is starting a personal Wiki. Basically, it becomes a repository of ideas that you have, that eventually you can go back and flesh out. When you get an idea for an article (or anything else), you can basically just create a post with a title in it. Then you can go back and fill in the content as you get the time and inclination.<br /><br />A few other really good points he made:<br /><ul><li>if a goal doesn't effect your behavior today, it's not a good goal (my interpretation: do something today to move yourself forward.)</li><li>if you want to write a book, a book is made of chapters, a chapter is made of sections, a section is pretty much an article, and what's an article but a glorified blog post?</li><li>get out there and teach/speak to really learn something (and get more exposure)</li><li>write and post short tutorials as you learn to do things. Those short tutorials also become good entry points for people learning to do something and get you some more exposure.</li></ul>All in all, it was a great talk, probably the best of the keynote speeches, and worth sticking around after lunch for :).</span></span>Jeffrey Eriksonhttp://www.blogger.com/profile/05123996612107368819noreply@blogger.com1