This is the title

This is the text.

This is the text that will wrap around the image.

Grails link with additional parameters

As I have said before, I love how easy it is to create links in Grails. However, when I was starting out I could never remember the syntax when I needed more information on the URL than just the ID.

Lets say I have a UrlMapping (grails-app/conf/UrlMapping.groovy) of:

"/player/photos/$id?/matchReport/$matchReportId?" {
     controller = "player"
     action = "photos"
 }

I always had problems remembering how to get the matchReportId onto the URL. As with so many things in Grails it turns out to be very simple; use the params parameter:

<g:link controller="player" action="photos" id="${matchPlayer.player.id}" params="[matchReportId:matchPlayer.matchReport.id]">

and good ol’ Grails is smart enough to build the URL like

rfw/player/photos/6/matchReport/26

Accessing Grails Config from a Grails Service

Grails configuration, particularly environment specific, information is kept in grails-app/conf/Config.groovy.

Access to this information is very easy in the presentation layer (controllers, gsp) using:

def imagesDir = grailsApplication.config.uploadDir

You can use this same mechanism from within a service; you just have to inject the grailsApplication into the service

class NewsService {
     def grailsApplication
     ...
     def imagesDir = grailsApplication.config.uploadDir

If you get an error message similar to the following, then the grailsApplication has  not been injected:

groovy.lang.MissingPropertyException: No such property: grailsApplication for class: NewsService

Creating a link in a Grails Service

I love how easy it is to create a link in Grails but often I want to use this same mechanism to create a link in a Service. For example, I have a service that sends out a News Report to a list of subscribers. There a links in the generated email back to the website.

Creating a link in a service turns out to be quite simple. I found this work around at http://jira.codehaus.org/browse/GRAILS-2605.

def g = new org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib()
 def visitUs = g.createLink(controller: 'site', action: 'index', absolute: 'true')
 def manageSubscriptions = g.createLink(controller: 'comm', action: 'index', absolute: 'true')

The absolute: ‘true’ is really important as I am embedded these links in an email.

Grails URLMapping

Given this URLMapping

"/news/show/$id?/item/$itemId?" {
 controller = "news"
 action = "show"
 }

results in the following params:

URL: http://localhost:8080/rfw/news/show
params: [“action”:”show”, “controller”:”news”]

URL: http://localhost:8080/rfw/news/show/1
params: [“id”:”1″, “action”:”show”, “controller”:”news”]

URL: http://localhost:8080/rfw/news/show/1/item
params: [“id”:”1″, “action”:”show”, “controller”:”news”]

URL: http://localhost:8080/rfw/news/show/1/item/4
params: [“id”:”1″, “action”:”show”, “controller”:”news”, “itemId”:”4″]

Hibernate Mapping

I often want to use a stored procedure to return a scalar value such as a count rather than a mapped object.

I find the best place to do this in the hibernate mapping file (.hbm.xml). In fact this is one of the reasons I like the mapping files over annotations. (I find the annotation syntax for named queries really hard to work with.)

In order for a named query to use a stored procedure, callable must be set to true.

To return a scalar value rather than a mapped object use return-scalar.

I have shown the same thing (getNumSubscritpions2) using native SQL rather than a stored procedure. In this example you don’t need the  <![CDATA[ … ]]>, but I always include them just to be safe; if you use <, or > in your SQL, things start to break down if you have not wrapped the SQL with CDATA.

<hibernate-mapping>

 <class name="className" table="tablename" select-before-update="true">
 </class>

 <sql-query name="getNumSubscriptions" callable="true">
 <return-scalar column="num_subscriptions"  type="java.lang.Integer" />
 { call pr_get_NumSubscriptions( '','', :labId, :programId, :subscriptionYear) }
 </sql-query>

<sql-query name="getNumSubscriptions">
 <return-scalar column="cnt"  type="java.lang.Integer" />
 <![CDATA[
 select count(distinct subscription_id) as cnt
 from v_Subscriptions (nolock)
 where lab_entity_id = :labId
 and program_id = :programId
 and test_event_year = :subscriptionYear
 and subscription_type_code not in ('SAMPLE_ONLY')
 ]]>
 </sql-query>

</hibernate-mapping>

and calling a name query in your application is simple:

Integer count  = (Integer)_entityManager.createNamedQuery( "getNumSubscriptions")
   .setParameter( "labId", labId)
   .setParameter( "programId", programId)
   .setParameter( "subscriptionYear", subscriptionYear)

   .getSingleResult();
if( count != null) {
    numSubscriptions = count.intValue();
 }

SQLServer date format

I always have problems with the date format for various databases.

Here is a date format that works with SQL Server

SELECT * FROM DateSample
WHERE DateVal = ‘2002-02-28’

Acceptance Tests

Accpetance Tests are executable specifications. They verify a product’s correctness from a business perspective.

According to Andy Dassing (http://tech.groups.yahoo.com/group/fitnesse/message/10115)

Acceptance Tests insure the right code is built … while Unit Tests insure the code is build right.

Acceptance Tests are written in the language of the domain.

An Acceptance Test should verify a single aspect of a User Story.

When all Acceptance Tests pass, the system is complete.

What about maintenance?

An extract from Mike Cohn’s User Stories Applied concerns me because I don’t know what artifacts I have available when maintaining the software.

Use cases are often permanent artifacts that continue to exist as long as the product is under active development or maintenance. Stories, on the other hand, are not intended to outlive the iteration in which they are added to the software.

After the software is build how do I maintain the software? How do a find out what the system should do if the story has been ripped up? If the story is not intended to outlive the iteration, what about the acceptance tests? If a user story changes surely I would use the existing story and acceptance tests to understand the impact of the change. The code can not be the only documentation for a system as only a small part of the team (the developers) can understand the code.

One of my biggest concerns about agile is that it is all about developing software are not about maintaining software; the maintenance cost over the life time of a piece of software is far bigger than the upfront development cost.

Agile Strengths

Agile allows a project to start without needing a complete set of requirements. Agile acknowledges the fact that customers do not know all the requirements of the system before the process begins. As the project progresses, everyone learns more about the system under construction; ideas and understanding changes. Acknowledging  that change is inevitable while providing a way to manage this change is one of the strengths of an agile process.