But it’s only for 64-bit Intel-based Macs.
More detail here.
Wednesday, 30 April 2008
Tuesday, 29 April 2008
A vmarg For Every Occasion
This is for any crazy cats out there that are using Eclipse 3.x on 64bit Linux with the latest J2SE 6 to do Groovy stuff - if Eclipse is crashing alot I just might have the solution for you.
Nothing odd about Eclipse crashing you say (fair) but it just may be that you've run aground on a brand new JVM bug that's got everybody posting those lovely hs_err_pid files as attachments on various forums so that we can all read them in detail later. Now for the great bit - another zany vmarg from the guys in white coats at Sun just may fix your issue:
-XX:CompileCommand=exclude,org/eclipse/core/internal/dtree/DataTreeNode,forwardDeltaWith
Add it to your eclipse vmargs setting in your eclipse.ini, stir twice and repeat as needed.
Nothing odd about Eclipse crashing you say (fair) but it just may be that you've run aground on a brand new JVM bug that's got everybody posting those lovely hs_err_pid files as attachments on various forums so that we can all read them in detail later. Now for the great bit - another zany vmarg from the guys in white coats at Sun just may fix your issue:
-XX:CompileCommand=exclude,org/eclipse/core/internal/dtree/DataTreeNode,forwardDeltaWith
Add it to your eclipse vmargs setting in your eclipse.ini, stir twice and repeat as needed.
Making your own builder
I've been playing around with implementing a custom builder the last few days. There are some examples on how to do this on the groovy site, but a fews things weren't immediately obvious, so I thought I give a full example and point a couple of things out.
The problem:
I wanted an easy way of building a graph of objects based on the NavElement class below from some sort of configuration.
However, if we could use the same groovy config closure to generate the object graph directly with our own custom builder, we can save ourselves this extra step AND the need for marshalling code from XML to our object graph. We can also make the groovy config closure less verbose. Let's look at how we might simplify groovy config closure.
Make a builder
Builder Support
So here is the Builder implementation for our example.
There are a few things to take note of
1. The createNode methods
These methods are called as each node in the closure is evaluated. In our example, which is fairly simple, we delegate all the over-loaded methods to the most complex version. This simply news up a NavElement based on the node name and sets the properties on the new NavElement. You'll note we do nothing with value parameter. We rely on the BuilderSupport class to take care of the recursive calls to the createNode for the nested elements. I have highlighted in the closure snippet below how the parameters, name, attributes and value, map to the closure elements for a particular node.
2. The getCurrentNode method
This returns the current node, which returns the current node in the closure that is being evaluated. In our example, we need to use this method to add any nodes that are being created to the children of the currentNode.
3. The setParent method. This is a convenient hook to allow us to set the parent of any node we are creating.
That's it! Here is a bit of test code that proves it works
The problem:
I wanted an easy way of building a graph of objects based on the NavElement class below from some sort of configuration.
class NavElement {In the past, XML would have been the obvious format for the configuration, which would then be turned into java objects via something like commons digester.
NavElement parent
String name
String controller
String action
List children = []
boolean selected
boolean equals(other) {
// omitted
}
int hashCode() {
// omitted
}
}
<navbar>However, now we are Groovy, some new options present themselves. Firstly, we can represent the XML in groovy code and use MarkupBuilder to turn the config code into XML, if we prefer.
<navelement name="Create">
<navelement name="Article" controller="article" action="create">
</navelement>
<navelement name="'Admin'" role="administrator">
<navelement name="Create" controller="user" action="create">
<navelementt name="List" controller="user" action="list">
</navelement>
</navbar>
navBar {Obviously there is no advantage to this in this particular case - we are not dynamically building the closure for example. In fact now we now have the extra, albeit trivial, task of converting the groovy config closure to XML.
navElement(name:'Create')
navElement(name:'Article', controllerName:'article', action:'create')
}
navElement(name:'Admin') {
navElement(name:'Create', controllerName:'user', action:'create')
navElement(name:'List Users', controllerName:'user', action:'create')
}
}
However, if we could use the same groovy config closure to generate the object graph directly with our own custom builder, we can save ourselves this extra step AND the need for marshalling code from XML to our object graph. We can also make the groovy config closure less verbose. Let's look at how we might simplify groovy config closure.
navBar {Now we need to implement a builder that can turn this config closure into our object graph. To do this, the groovy api provides an abstract BuilderSupport class to extend and implement. There are a couple of examples about this class on the groovy website.
create {
Article(controllerName:'article', action:'create')
}
Admin {
Create( controllerName:'user', action:'create')
'List Users'(controllerName:'user', action:'create')
}
}
Make a builder
Builder Support
So here is the Builder implementation for our example.
class NavBuilder extends BuilderSupport {
public static NavBuilder newInstance() {
return new NavBuilder();
}
protected void setParent(Object parent, Object child) {
child.parent = parent
}
protected Object createNode(Object name) {
createNode name, null, null
}
protected Object createNode(Object name, Object value) {
createNode name, null, value
}
protected Object createNode(Object name, Map attrs) {
createNode name, attrs, null
}
protected Object createNode(Object name, Map attrs, Object value) {
def node = new NavElement(name: name)
if (attrs) {
attrs.each {property, val ->
if (node.properties.keySet().contains(property)) {
node."${property}" = val
}
}
}
if (getCurrent()) {
getCurrent().children << node
}
return node
}
}
There are a few things to take note of
1. The createNode methods
These methods are called as each node in the closure is evaluated. In our example, which is fairly simple, we delegate all the over-loaded methods to the most complex version. This simply news up a NavElement based on the node name and sets the properties on the new NavElement. You'll note we do nothing with value parameter. We rely on the BuilderSupport class to take care of the recursive calls to the createNode for the nested elements. I have highlighted in the closure snippet below how the parameters, name, attributes and value, map to the closure elements for a particular node.
navBar(controllerName:'home', action:'index') {
Admin {
Create( controllerName:'user', action:'create')
'List Users'(controllerName:'user', action:'create')
}
}
2. The getCurrentNode method
This returns the current node, which returns the current node in the closure that is being evaluated. In our example, we need to use this method to add any nodes that are being created to the children of the currentNode.
3. The setParent method. This is a convenient hook to allow us to set the parent of any node we are creating.
That's it! Here is a bit of test code that proves it works
class NavBuilderTests extends GroovyTestCase {
void testBuildingOfNavElements() {
navBuilder = new NavBuilder()
navBar =
navBuilder.navBar() {
publisher()
create {
'create article'(controller:'articleController', action:'create')
}
}
assertEquals ('navBar', navBar.name)
assertNotNull navBar.children
assertEquals 2, navBar.children.size()
assertEquals ('publisher', navBar.children[0].name)
assertEquals ('navBar', navBar.children[0].parent.name)
def createNavElement = navBar.children[1]
assertEquals ('create', createNavElement.name)
assertEquals ('navBar', createNavElement.parent.name)
assertEquals 1, createNavElement.children.size()
def articleCreateNavElement = createNavElement.children[0]
assertEquals ('create article', articleCreateNavElement.name)
assertEquals ('articleController', articleCreateNavElement.controller)
assertEquals ('create', articleCreateNavElement.action)
assertEquals ('create', articleCreateNavElement.parent.name)
}
}
What happens when you throw exceptions from services
class LolController {
def sessionFactory
def lolService
def gimmehCheezburger = {
def kitteh = Lolcat.get(params.id)
try {
lolService.canHasCheezburger(kitteh)
assert sessionFactory.currentSession.contains(kitteh)
} catch (EpicFailException wtf) {
assert !sessionFactory.currentSession.contains(kitteh)
}
render(view: 'lolcat', model: [lolcat: kitteh])
}
}
Note that the domain object 'kitteh' becomes detached from the hibernate session if the service throws an exception. This would cause reads of the object's lazy-loaded associations in the view rendering phase to fail.
If this is really what you want to do (it looks unpleasantly like controlling program flow via exceptions) you can use
kitteh.refresh()
in the catch block to re-attach the object to the hibernate session.Monday, 28 April 2008
Design Coding
The Poetic Prophet (AKA The SEO Rapper) is back with another rap, this time describing how web standards and proper design can affect the ranking and conversion of pages on your site.
It's good hearty information delivered in a fun way.
http://www.molly.com/2008/04/07/design-coding-rap-for-the-rest-of-us/
It's good hearty information delivered in a fun way.
http://www.molly.com/2008/04/07/design-coding-rap-for-the-rest-of-us/
Annoying Grails upgrade message in IntelliJ
You're probably seeing a dialog with the message "Application has Grails version 1.0.2, but current Grails version is undefined. Upgrade application?" every time IntelliJ re-scans the project.
I've posted a question about this on the IntelliJ forums for anyone who wants to keep an eye on it.
Update: SOLVED! This was caused by the patched version of grails-core-1.0.2.jar created by the prepare script which screwed up the manifest.mf file in the jar. I have updated the script so it no longer does this. You will need to replace $GRAILS_HOME/dist/grails-core-1.0.2.jar (that's %GRAILS_HOME%\dist\grails-core-1.0.2.jar for Windows people) with the original version from the Grails distro (on the mirror) then run the new version of the prepare script I checked in (revision 3325).
I've posted a question about this on the IntelliJ forums for anyone who wants to keep an eye on it.
Update: SOLVED! This was caused by the patched version of grails-core-1.0.2.jar created by the prepare script which screwed up the manifest.mf file in the jar. I have updated the script so it no longer does this. You will need to replace $GRAILS_HOME/dist/grails-core-1.0.2.jar (that's %GRAILS_HOME%\dist\grails-core-1.0.2.jar for Windows people) with the original version from the Grails distro (on the mirror) then run the new version of the prepare script I checked in (revision 3325).
Labels:
intellij
Friday, 25 April 2008
Cascading validation
This has confused me for a while. If we have these classes:
You will find this test fails because the validate() call does not cascade to the aggregated object:
The trick is validate will only cascade in the same circumstances that a save would cascade, so if we add
class Lolrus {
String name
Bukkit bukkit
}
class Bukkit {
String contents
static constraints = {
contents(validator: {
return 'o.noes'
})
}
}
You will find this test fails because the validate() call does not cascade to the aggregated object:
void testErrorsOnAssociations() {
def lolrus = new Lolrus(name: 'jerome')
lolrus.bukkit = new Bukkit(contents: 'fish')
assert !lolrus.validate()
}
The trick is validate will only cascade in the same circumstances that a save would cascade, so if we add
static belongsTo = [lolrus: Lolrus]
to the Bukkit class the validation cascades properly and the test works.
Thursday, 24 April 2008
Browsing the grails source code online
This came handy to me as well a few times:
http://fisheye.codehaus.org/browse/grails
http://fisheye.codehaus.org/browse/grails-plugins
kosziszia,
Dori
http://fisheye.codehaus.org/browse/grails
http://fisheye.codehaus.org/browse/grails-plugins
kosziszia,
Dori
Grails plugin architecture
This is probably not new for most of you but was very helpful for me to understand where the 'black magic' comes from.
Slides:
http://www.grails-exchange.com/files/GraemeRocher%20-%20GrailsPlug-InArchitecture.pdf
Video:
http://www.theserverside.com/news/thread.tss?thread_id=47680
bye,
D
Slides:
http://www.grails-exchange.com/files/GraemeRocher%20-%20GrailsPlug-InArchitecture.pdf
Video:
http://www.theserverside.com/news/thread.tss?thread_id=47680
bye,
D
o.hai and ...
I am not one for big speeches...but thought writing to this blog might be a good way to say what I've wanted to say for while.
I have never really taken the opportunity to thank the team for all your hard work and efforts you have put into this project.
When I think back to how we started this project and where we are now I cannot believe that we have delivered such a quality product that looks "absolutely fabulous" (despite it being borderline pornographic). I am so proud of what you have achieved.
We have never worked this way and have never imagined that things could be this great. This is the most enjoyable project that I have ever been a part of and that is simply down to the people in this team.
For those of you who are experienced in agile projects I would like to especially thank you for your patience and support. You have helped grow our capability and enabled us to think about how things can be achieved with customer focus, simplicity and quality in mind. The challenges we face are not easy but with coaching at all levels, with the small steps we make everyday, we are a step closer to where we want to be.
Your discipline and your belief in what you do shines through and gives us the direction we need to make this a reality for us.
For the "permies" I know that things have been hard with such a new way of working, whilst tackling such a steep learning curve in your own domains. But despite all of this you have remained dedicated, open to all the changes and taken everything on board. You have shown such positivity in this approach and stepped up to the challenge. It takes courage to make so many changes. I really look forward to you all taking this to another level, being able to show how much you have learnt and supporting those with little experience in what we do.
You know yourselves how much you have achieved over the last 6 months.
There has been a lot of hard work by everyone in getting here, but we are all here together and best of all - we are moving forward together and continuing to make things better.
Thank you all for making this such a great environment to work in, despite my outbursts, I love all the laughs we have about LOL cats(even though they are still not funny), the flying bullets and that really annoying helicopter. You are a fantastic team..........
Thank you.
k.thx.bye
I have never really taken the opportunity to thank the team for all your hard work and efforts you have put into this project.
When I think back to how we started this project and where we are now I cannot believe that we have delivered such a quality product that looks "absolutely fabulous" (despite it being borderline pornographic). I am so proud of what you have achieved.
We have never worked this way and have never imagined that things could be this great. This is the most enjoyable project that I have ever been a part of and that is simply down to the people in this team.
For those of you who are experienced in agile projects I would like to especially thank you for your patience and support. You have helped grow our capability and enabled us to think about how things can be achieved with customer focus, simplicity and quality in mind. The challenges we face are not easy but with coaching at all levels, with the small steps we make everyday, we are a step closer to where we want to be.
Your discipline and your belief in what you do shines through and gives us the direction we need to make this a reality for us.
For the "permies" I know that things have been hard with such a new way of working, whilst tackling such a steep learning curve in your own domains. But despite all of this you have remained dedicated, open to all the changes and taken everything on board. You have shown such positivity in this approach and stepped up to the challenge. It takes courage to make so many changes. I really look forward to you all taking this to another level, being able to show how much you have learnt and supporting those with little experience in what we do.
You know yourselves how much you have achieved over the last 6 months.
There has been a lot of hard work by everyone in getting here, but we are all here together and best of all - we are moving forward together and continuing to make things better.
Thank you all for making this such a great environment to work in, despite my outbursts, I love all the laughs we have about LOL cats(even though they are still not funny), the flying bullets and that really annoying helicopter. You are a fantastic team..........
Thank you.
k.thx.bye
Dynamic methods on domain classes, controllers and taglibs
If you want to dig into what the various dynamic methods attached to Grails artefacts actually do under the hood you can find all the code in:
- domain classes:
- controllers and taglibs:
... and for a possible alternative to Gant
I'm list whoring again... from the groovy-user list, just announced
http://www.gradle.org
Gradle is a build system which provides:
The obvious question.. how does it compare to Gant, is visited here
http://www.gradle.org
Gradle is a build system which provides:
- Flexible general purpose build tool like Ant.
- Switchable, build-by-convention frameworks a la Maven. But without lock in
- Support for multi-project builds.
- Powerful dependency management (based on Apache Ivy).
- Full support for your existing Maven or Ivy repository infrastructure
- Optional support for transitive dependency management without the need for remote repositories and pom.xml or ivy.xml files.
- Ant tasks as first class citizens.
- A wrapper to run Gradle builds on machines where Gradle is not installed (e.g. continuous integration server)
- Groovy build scripts.
The obvious question.. how does it compare to Gant, is visited here
JAWR Plugin Announced
Just spotted this on the grails-user list....
Jawr is an Open Source library which offers two complementary uses for java and groovy web applications in which javascript is heavily used:
/jawr+plugin
Jawr is an Open Source library which offers two complementary uses for java and groovy web applications in which javascript is heavily used:
- First, it's a productivity tool, since it allows to develop javascript components in separate files, each representing a module, as opposed to having all the code in one or two files for performance reasons. Working with separate files makes development, maintenance and version control a lot easier.
- On the other hand, Jawr is a performance tool which will perceivably improve page loading times. When in production mode, all the modules which were split in separate files are bundled together (into one or several files, as per configuration), then minified, then compressed and sent to the client using aggressive caching headers. This reduces the number of HTTP requests required to load a full page and also the size in kilobytes that a user must download. Jawr implements many of the good practices defined in this very interesting article which I recommend everyone to read: serving javascript fast.
Consistency in custom validators
There are 4 different ways you can get custom validators to attach errors to your domain objects.
In addition, on the 'cheezburger' and 'bukkit' validators Grails will automatically attach three arguments:
I've created a helper method ValidationUtils.rejectValue(target, errors, fieldName, code, args) that will do all this for you which enables error codes and message arguments to be consistently standardised no matter which type of validator you're writing.
- Return true/false/null
- Return an error code String
- Return a List consisting of the error code and args
- Attach the errors yourself (only available in the 3 argument validator)
class Lolcat {will attach the following error codes to an instance's fields when validate is called (the bolded value is the default returned by obj.error.code):
String cheezburger
String bukkit
String flavr
static constraints = {
cheezburger(validator: {
return false
})
bukkit(validator: {
return 'epic.fail'
})
flavr(validator: { value, target, errors ->
errors.rejectValue('flavr', 'epic.fail')
})
}
}
- cheezburger
- lolcat.cheezburger.validator.error.Lolcat.cheezburger
- lolcat.cheezburger.validator.error.cheezburger
- lolcat.cheezburger.validator.error.java.lang.String
- lolcat.cheezburger.validator.error
- lolcat.cheezburger.validator.invalid.Lolcat.cheezburger
- lolcat.cheezburger.validator.invalid.cheezburger
- lolcat.cheezburger.validator.invalid.java.lang.String
- lolcat.cheezburger.validator.invalid
- validator.invalid.Lolcat.cheezburger
- validator.invalid.cheezburger
- validator.invalid.java.lang.String
- validator.invalid
- bukkit
- lolcat.bukkit.validator.error.Lolcat.bukkit
- lolcat.bukkit.validator.error.bukkit
- lolcat.bukkit.validator.error.java.lang.String
- lolcat.bukkit.validator.error
- lolcat.bukkit.epic.fail.Lolcat.bukkit
- lolcat.bukkit.epic.fail.bukkit
- lolcat.bukkit.epic.fail.java.lang.String
- lolcat.bukkit.epic.fail
- epic.fail.Lolcat.bukkit
- epic.fail.bukkit
- epic.fail.java.lang.String
- epic.fail
- flavr
- epic.fail.Lolcat.flavr
- epic.fail.flavr
- epic.fail.java.lang.String
- epic.fail
In addition, on the 'cheezburger' and 'bukkit' validators Grails will automatically attach three arguments:
- field name
- class name
- field value
I've created a helper method ValidationUtils.rejectValue(target, errors, fieldName, code, args) that will do all this for you which enables error codes and message arguments to be consistently standardised no matter which type of validator you're writing.
view compiled gsp code
In order to find the actual compiled gsp code for a given url add ?showSource to the query string.
See http://piragua.com/2008/03/15/viewing-the-source-of-a-compiled-gsp-in-grails/
See http://piragua.com/2008/03/15/viewing-the-source-of-a-compiled-gsp-in-grails/
Wednesday, 23 April 2008
Groovy Cookbook
Here's a link to a groovy cookbook that I have found useful over time:
http://pleac.sourceforge.net/pleac_groovy/index.html
http://pleac.sourceforge.net/pleac_groovy/index.html
Subscribe to:
Posts (Atom)