Grails Finance 0.1

This entry is part of 15 in the series Grails Finance

Grails is an automagical RAD web application framework in the style of Ruby on Rails. Grails uses Groovy as its main language. You could also substitute it with Java, but that would be less fun. As an example I made a small web application for financial data.

Installation

In Mac Ports this command installs Grails

1
sudo port install grails

to be exact it installs version 1.3.2 Just this week version 1.3.3 was released. You still need to put Grails in your path

1
2
export GRAILS_HOME=/opt/local/share/java/grails
export PATH=$PATH:$GRAILS_HOME/bin

Creating the app

Grails lets you generate code and configuration files from the command line or if you are a wimp you can use an IDE instead. This command generates the application

1
2
grails create-app finance
cd finance

You can already run the application,

1
grails run-app

but of course, there is not much to see yet.

Initial appCreate screenCreate screen

Grails MVC

Grails reinvents MVC and provides scripts for it. Here is how we can create a controller

1
2
3
4
5
6
7
8
9
10
11
12
grails create-controller finance
 
Resolving dependencies...
Dependencies resolved in 1439ms.
Running script /opt/local/share/java/grails/scripts/CreateController.groovy
Environment set to development
    [mkdir] Created dir: ... finance/grails-app/controllers/finance
Created Controller for Finance
    [mkdir] Created dir: ... finance/grails-app/views/finance
  [groovyc] Compiling 1 source file to /Users/ivanidris/Projects/grails/finance/target/classes
    [mkdir] Created dir: ... finance/test/unit/finance
Created Tests for Finance

Grails generates some tests for the lazy Agile developer and a controller

1
2
3
4
5
package finance
 
class FinanceController {
    def index = { }
}

Now we can create some entity model classes or as Grails calls them domain classes

1
grails create-domain-class datasource

The datasource class will store information for the financial data sources. They will all be free, of course, since this is a home project.

1
2
3
4
5
6
7
8
9
package finance
 
class Datasource {
    String name
    String description
 
    static constraints = { 
    }   
}

Tweaking

In grails-app/conf/DataSource.groovy you can find configuration settings for different environments such as test, development and production. I changed the development settings so that the database will be persisted to a file for now. Every time Grails notices a change in the code the server is restarted. I changed the dbCreate parameter otherwise with the initial value of create-drop the database would have been dropped.

1
2
3
4
5
6
    development {
        dataSource {
            dbCreate = "update" // one of 'create', 'create-drop','update'
            url = "jdbc:hsqldb:file:devDB;shutdown=true"
        }   
    }

Scaffolding feature

Scaffolding gives you basic CRUD screens for your domain classes. I noticed a feature, when I setup scaffolding for Datasource in the main controller.

1
2
3
4
5
6
package finance
 
class FinanceController {
    def scaffold = Datasource  
    def index = { } 
}

The following stack trace was produced

ERROR view.ScaffoldingViewResolver  - Error generating scaffolded view [/finance/index]: /opt/local/share/java/grails/src/grails/templates/scaffolding/index.gsp (No such file or directory)
java.io.FileNotFoundException: /opt/local/share/java/grails/src/grails/templates/scaffolding/index.gsp (No such file or directory)
	at java.io.FileInputStream.open(Native Method)
	at java.io.FileInputStream.(FileInputStream.java:106)
	at java.lang.Thread.run(Thread.java:637)

The error message although correct was not very helpful. The fix was to change the controller to this

1
2
3
4
5
package finance
 
class FinanceController {
    def scaffold = Datasource  
}

Constraints

You can define constraints for your domain classes. For instance, here name is required to be not null or blank. There are a few other possible constraints, such as defining a field to be an email address or URL.

1
2
3
4
5
6
7
8
9
10
11
12
package finance
 
class Datasource {
    String name
    String description
    Date added = new Date()
 
    static constraints = { 
      name(blank:false)
      description(maxSize:255)
    }   
}

More commands

At a certain point you will want to make a WAR

1
2
3
grails war
 
Done creating WAR  ... finance/target/finance-0.1.war

Also you might be interested in how many files and lines of code were written

1
2
3
4
5
6
7
8
9
10
11
grails stats
 
    +----------------------+-------+-------+
    | Name                 | Files |  LOC  |
    +----------------------+-------+-------+
    | Controllers          |     1 |     4 | 
    | Domain Classes       |     1 |    10 | 
    | Unit Tests           |     2 |    24 | 
    +----------------------+-------+-------+
    | Totals               |     4 |    38 | 
    +----------------------+-------+-------+

Not bad for a few minutes work. Strange that the configuration files and views are not listed.

Instrument type

Now it’s time to get serious about the domain model. Well not production type serious, more secret home weekend project type serious :). First let’s define InstrumentType. Every instrument would have a type, unless of course the type is unknown. The 1:1 relation description is set in belongsTo. The type is set to be unique. It is recommended to have a toString implementation, otherwise Grails will display the classname and record id by default in the UI.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package finance
 
class InstrumentType {         
    static belongsTo = Instrument   
 
    String type                
    String description         
 
    static constraints = {     
      type(unique:true, blank:false)  
    } 
 
    String toString() {
      "${type}"
    }   
}

Instrument

The amazing thing about the financial industry, is that, there are no real identification standards. You would think, that for such a multi billion type business, some general scheme would exist. Each data vendor has their own symbology so for the same instrument we would have different records. One for each data source.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package finance
 
class Instrument {
    String name
    String symbol
    InstrumentType instrumentType
    Date added = new Date()
    Datasource source
 
 
    static constraints = {
      name(unique:true, blank:false)
      symbol(unique:true, blank:false)
      source(blank:false)
    }
 
    static mapping = {
      instrumentType lazy:false
    }
 
    static hasMany = [ contains:Instrument, values:FieldValue]
 
    String toString() {
      "${name} ${symbol} ${source}"
    }
}

We can have the instrument type be lazy fetched or in this case eagerly. hasMany here indicates that an instrument can contain other instruments and could have many values.

Field

A field could be an attribute that does not change a lot or a price. It might be useful to have a field type domain class as well, but I decided to keep things simple for now.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package finance
 
class Field {
    String name
    String description
 
    static constraints = { 
       name(blank:false)
    }   
 
    static hasMany = [ values : FieldValue ]
 
    String toString() {        
      "${name}"
    } 
}

FieldValue

Value is a keyword I think, just like values is a SQL keyword. Value is not allowed by groovyc

Apparent variable 'Value' was found in a static scope but doesn't refer to a local variable, static field or class. Possible causes:
  [groovyc] You attempted to reference a variable in the binding or an instance variable from a static context.
  [groovyc] You misspelled a classname or statically imported field. Please check the spelling.
  [groovyc] You attempted to use a method 'Value' but left out brackets in a place not allowed by the grammar.
  [groovyc]  @ line 11, column 33.
  [groovyc]        static hasMany = [ values : Value ]
  [groovyc]                                    ^
  [groovyc] 
  [groovyc] 1 error

For the field values we need a proper timestamp. java.util.Date is not good enough for that so we will need Jodatime. Fortunately Grails has a whole plugin ecosystem, including a Jodatime plugin that we can install.

1
2
3
grails install-plugin joda-time
grails install-joda-time-gorm-mappings
grails install-joda-time-templates

The value is stored as a String. This is not type safe, so it would have been better to have a value table for each data type.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package finance
 
import org.joda.time.*
import org.joda.time.contrib.hibernate.*
 
class FieldValue {
    String val 
    DateTime timestamp
    static constraints = { 
      val(blank:false)
      timestamp(blank:false)
    }   
 
    static belongsTo = [Instrument, Field]
 
    String toString() {        
      "${val} ${timestamp}"    
    } 
}

Final scaffolding

Now we need to run

1
2
3
4
5
grails create-controller Datasource
grails create-controller Field
grails create-controller FieldValue
grails create-controller Instrument
grails create-controller InstrumentType

to create a controller for each domain class. Then put def scaffold = true in each controller to have Grails create basic CRUD functionality.

Instrument list

Conclusion

Grails is really easy to use and definitely more fun than the Java alternatives. Whenever I have time, I will retrieve some data and populate the database with some values. The next step would be to do some analysis on the data.

Series Navigation
By the author of NumPy Beginner's Guide, NumPy Cookbook and Instant Pygame. If you enjoyed this post, please consider leaving a comment or subscribing to the RSS feed to have future articles delivered to your feed reader.
Share
This entry was posted in programming and tagged , , . Bookmark the permalink.

2 Responses to Grails Finance 0.1

  1. Wealth Management says:

    Found your website very informative, as a financial wealth management company your articles have proven to be very good, thank you.

  2. Kent says:

    Ive already been following on from the web site for a thirty day period approximately and have picked up a huge amount of data and also cherished the strategy you have organised your web site. I will be looking to work my own very personal blog site even so. I do think it’s also general and I must consentrate on quite a lot of scaled-down subjects. Being as much as possible to any or all folks is not everything it’s broke up to be.

Comments are closed.