I have all but abandoned this blog. I think it has been over a year since I posted anything here. At this point, writing here reminds me of Forest Whitaker's character in the movie Phenomenon telling his story over a radio that he knows no one is listening to. That is fine.
My parents divorced when I was 10 years old. My Mother was put in a position where she had to take action. She put myself and my 2 sisters in the car and drove across the country to St. Louis where she had grown up and where her family lived. We had made the trip before for summer vacations but this time it was for good. I can only imagine how terrifying this must have been for her. Imagine a 10 year old car, kids 10, 12 and 13, some clothes and nothing else, nothing. I expect many people couldn't do it.
We got to St. Louis where there was lots of family support. My Mother had 2 brothers and a sister all in St. Louis along with her parents. Her sister Brenda took us into her house. She had a great place in a great neighborhood in the suburbs. Brenda was a single Mom with 3 kids of her own but her home was ours. I was young enough that I would not have been involved in financial discussions but I am sure this was a hardship for her take on 4 more people. My Mother had been a housewife and I think she left our home in Virginia with no money. If she had any money, I don't think it could have been very much. 3 kids, no money, no career.
During those first few months when we lived at Aunt Brenda's house, it really was a pretty good time for me. I spent time with my cousins. We had a great place to live. We did a lot of fun things on the weekends. It was tough working out the deal with my Dad no longer being with us but the day to day was good and the reason it was good is that Brenda took us in and made sure we had everything we needed. My grandparents, Uncles and Aunt were all there to provide support in lots of ways but it was Aunt Brenda's house we lived in and she bore a lot of the burden. I doubt she ever gave it a thought.
Aside from my Mother, it may be that Brenda is most responsible for our survival during that time, that of myself my Mother and my sisters. When I think about the time immediately following my parents' divorce, I think about the time I spent living in her house. We weren't living in a crappy motel or worse. Because of her we lived in a fantastic place and had everything we needed.
Today, Brenda's battle with cancer has come to a crushing end. I am crushed. I am crushed as I think about my cousins, her kids who are without her. I am crushed as I think about my Mother who just 2 months ago lost her Mother and now her sister.
Brenda was a tiny woman but a feisty take charge kind of woman. She didn't take any shit from anyone and if I worded it any other way, she might have taken offense.
I thank Brenda for everything she did for us. If I was a poet I would write a tribute to her. If I could paint I would paint a tribute to her. As it is, I will be thinking about her and the rest of the family and will do my best to be inspired by what she did for me and my family.
Today's Loss Thursday, August 18, 2011
Posted by Jeff Brown at 9:33 PM 11 comments
Switching Versions Of Grails (and other tools) Friday, April 23, 2010
I have a little trick that I have used for many years to switch back and forth between versions of development tools. For example, because of the work that I do day to day I often need to switch back and forth between different versions of Grails. Occasionally I will execute this trick while sitting with another developer or during a live coding presentation at a conference without even thinking about it. Often someone will notice and and stop me to ask "what was that?".
I have a directory below my HOME directory called Tools. This Tools directory is where I install development tools like Groovy, Grails, Gradle, Ant etc. For some of those tools, I may want to have numerous versions of the tool available. For example, I have the following subdirectories below Tools...
grails-1.0.5
grails-1.1.1
grails-1.1.2
grails-1.2-M4
grails-1.2.0
grails-1.2.0.RC1
grails-1.2.0.RC2
grails-1.2.1
grails-1.2.2
grails-1.3.0.RC1
grails-1.3.0.RC2
One thing I might do when I need to use a specific version of Grails is something like this...
export GRAILS_HOME=~/Tools/grails-1.2.2
export PATH=$GRAILS_HOME/bin:$PATH
One limitation of that approach is it is a lot of tedious typing. Another is that the change would only apply to the shell where that was executed. Normally if I am working with a particular version of Grails, I want that version to be in play in all open shells.
Instead of pointing GRAILS_HOME at a particular version of Grails, I create a symlink at ~/Tools/grails and that link points to one of the specific Grails version directories. GRAILS_HOME points to that symlink. If I am currently using Grails 1.2.2 and I want to switch to 1.3.0.RC2, I just move the symlink and leave GRAILS_HOME and PATH alone.
Moving the symlink is easy enough but I simplify it further by defining aliases in my ~/.profile. Those look something like this...
alias gr105='rm ~/Tools/grails && ln -s ~/Tools/grails-1.0.5 ~/Tools/grails'
alias gr111='rm ~/Tools/grails && ln -s ~/Tools/grails-1.1.1 ~/Tools/grails'
alias gr112='rm ~/Tools/grails && ln -s ~/Tools/grails-1.1.2 ~/Tools/grails'
alias gr12='rm ~/Tools/grails && ln -s ~/Tools/grails-1.2.0 ~/Tools/grails'
alias gr121='rm ~/Tools/grails && ln -s ~/Tools/grails-1.2.1 ~/Tools/grails'
alias gr122='rm ~/Tools/grails && ln -s ~/Tools/grails-1.2.2 ~/Tools/grails'
alias gr130rc1='rm ~/Tools/grails && ln -s ~/Tools/grails-1.3.0.RC1 ~/Tools/grails'
alias gr130rc2='rm ~/Tools/grails && ln -s ~/Tools/grails-1.3.0.RC2 ~/Tools/grails'
# use my local development copy of Grails
alias grdev='rm ~/Tools/grails && ln -s /Users/jeff/Projects/grails/core ~/Tools/grails'
Now if I want to use Grails 1.2.2 I just open a shell and type "gr122".
I use the exact same approach for other tools that I may want to easily move from version to version.
I do all of this on OS X. The same trick should work on Linux. I don't know enough about cygwin to know if this can work on Windows or not. I expect that it probably would.
That is all I have. It isn't any big deal but is one of those little things that over the years numerous folks have asked me about and then expressed that they liked it well enough that they were going to do the same.
Enjoy!
Posted by Jeff Brown at 11:20 AM 22 comments
Grails, SpringSource And Clojure Thursday, July 30, 2009
I recently developed a Grails plugin which provides support for easily accessing Clojure code in a Grails app. The details of how the plugin works are covered at http://grails.org/plugin/clojure. That page includes a link to a brief video demonstration which is available at http://s3.amazonaws.com/jeffscreencasts/grails_clojure_demo.mov. Check it out.
Shortly after publishing the plugin I posted something about it on Twitter. Not too long after that a couple of other SpringSource folks tweeted about Clojure (here and here). I got a couple of questions (in jest I am sure) about SpringSource and Clojure. "Is SpringSource Moving To Clojure?". Of course not. SpringSource is not moving to Clojure. SpringSource is all about helping folks build serious applications for the JVM and most of that is done in Java. This is not news. I work on Groovy and Grails. Much of what I do is in Groovy. This too is not news. Making it easy for folks to use languages like Scala and Clojure while taking advantage of all the great stuff that Grails has to offer, that is appealing to me and that is why I developed the Clojure plugin.
Clojure is a really interesting language. There are others. The fact that 3 folks from SpringSource have expressed some kind of interest in Clojure shouldn't be all that surprising. There are probably even more folks at SpringSource who have some kind of interest in Clojure but for entertainment, lets focus on the 3 mentioned...
I am honestly not sure how many technologists work for SpringSource but for the sake of having a number to work with, lets say there are 50. Lets also say that Clojure is interesting enough that 15% of JVM developers are interested in learning more about it. I can't back that number up with any research, lets just go with it. If 15% of JVM developers are interested in the language and you take a random group of 50 JVM developers (the 50 in question are certainly not 50 random developers, these are the edge cutters which probably makes them more likely to be interested in keeping an eye on what is new, but work with the idea that they are random)... Do the math. No, really... Do the math. Do the math to figure out the likelihood that 3 of the 50 would be interested in Clojure. I challenge you to do the math in Clojure and post your solution in a comment here. Do it in Scala, Do it in Groovy. Pick a JVM language and do the math.
The simplest solution is probably not very interesting. Prefer a solution that shows off something interesting in your language of choice.
Hmmm... are you more likely to need to refer to the Clojure book, or the high school math book? ;)
Now, you have one more reason to tinker with a new language.
Enjoy.
Posted by Jeff Brown at 4:26 PM 24 comments
Labels: clojure springsource groovy
Grails 1.1 beta3 Is Out! Thursday, January 29, 2009
We are closing in on the much anticipated release of Grails 1.1. Today beta 3 was released. See the release notes.
A new feature that has not been documented yet involves new validation capabilities. Up to this point, domain classes and command objects within a Grails app have supported really powerful validation capabilities. See section 7 in The User Guide for info on how that works. What is new is now you can apply those same validation capabilities to any class within a Grails app, not just domain classes and command objects. Making a class validateable involves defining a static property called "constraints" and assigning a closure, just like you would in a domain class or a command object.
Second, you have to tell Grails about your validateable class. You have 2 options for doing that. One option is to mark you class with the org.codehaus.groovy.grails.validation.Validateable annotation. Another option is to define your validateable classes in grails-app/conf/Config.groovy by assigning a value to the grails.validateable.classes property. That would look something like this...
grails.validateable.classes = [ com.mycompany.dto.SomeClass, com.mycompany.SomeOtherClass]
An annotated class might look something like this...
// src/groovy/com/companyname/SomeClass.groovy
package com.companyname
import org.codehaus.groovy.grails.validation.Validateable
@Validateable
class SomeClass {
Integer age
String name
static constraints = {
age range: 16..66
name blank: false, size: 5..35
}
}
Note that if you are using the annotation based approach, Grails will search all classes in the app to find all of the @Validateables. While that isn't really a performance problem, you can tune that a bit by specifying some specific packages that Grails should search. To do that, assign a value to grails.validateable.packages in grails-app/conf/Config.groovy like this...
grails.validateable.packages = ['com.companyname.dto', 'com.companyname.someotherpackage']
If the grails.validateable.packages property has a value then Grails will only look in those packages (and packages below those packages) for classes marked with @Validateable.
While this is still beta software, I think the feature will end up being delivered in the final release pretty much like it is described above. If you have any input on that or any other features in Grails. We would love to hear from you. Bring it to the mailing list or file a JIRA issue.
Enjoy!
Posted by Jeff Brown at 7:26 PM 13 comments
Getting Groovy With "with" Thursday, November 13, 2008
UPDATE 12/15/2008: I committed a change yesterday that changes the behavior of the .with method to use DELEGATE_FIRST as the resolveStrategy instead of OWNER_FIRST. If you are not sure what that means, you should by the end of this post.
Strange enough title.
Let's start with a hypothetical conversation between a geeky developer and his much less geeky wife:
Jeff: Betsy, how are you?
Betsy: I am fine thanks. How are you?
Jeff: Betsy, I am fine thank you.
Betsy: Great.
Jeff: Betsy, you know my birthday is the day after tomorrow right?
Betsy: Yes, I haven't forgotten. You mention it about 9 times a day you know.
Jeff: Betsy, yes I know. Are we going to have an ice cream cake?
Betsy: Yes, I think that would be good.
Jeff: Betsy, are you going to buy me the new Opeth DVD?
Betsy: I will get it for you but that music sucks big time.
Jeff: Betsy, that is awesome. Thank you.
Betsy: Why do you keep saying "Betsy" at the beginning of every sentence?
Jeff: Betsy, I guess I am used to inflexible languages which aren't very expressive.
Um, what does any of that have to do with Groovy? Well, lets talk about the problem with this conversation (aside from the lady's lack of appreciation for Swedish heavy metal). What is wrong is Jeff begins each sentence with "Betsy". Why might he do that? One reason is so Betsy knows that he is talking to her. Clearly this isn't necessary. It isn't necessary because she already knows he is talking to her. A context has been established which makes the addressing unnecessary. Jeff began the conversation by addressing Betsy, they probably made eye contact and were in close proximity. Once the conversation started, there isn't much question about who each sentence is being directed to.
Again, what does any of that have to do with Groovy? Lets press on...
Consider the following Java code which prints out a specific date.
// PrintIndependenceDay.java
import java.util.Calendar;
import java.util.Date;
public class PrintIndependenceDay {
public static void main(String[] args) {
Calendar calendar = Calendar.getInstance();
calendar.clear();
calendar.set(Calendar.MONTH, Calendar.JULY);
calendar.set(Calendar.DATE, 4);
calendar.set(Calendar.YEAR, 1776);
Date time = calendar.getTime();
System.out.println(time);
}
}
Groovy developers can look at that and find quite a bit of noise that doesn't really have anything to do with what the code is trying to do but I want to focus on one specific thing. That one thing is all of the interaction with the calendar variable. Notice that we call clear() on the calendar, then call set() several times and later call getTime() on that same variable. All of those calls are prefixed with "calendar." so the compiler knows what we want to do. If we called "clear()" instead of "calendar.clear()", what would that mean? Are we calling the clear() method in this class? If that was our intent, it would not work because there is no clear() method. We have to prefix the call with an object reference so the compiler knows where to send the request. That seems to make sense. However, if we are going to do a bunch of things "with" the same object, wouldn't it be kind of nice if we could somehow do all of those things without all the repetition. Specifically, it might be nice if we could get rid of all of those "calendar." prefixes.
On to Groovy...
The following Groovy code does the same thing that the Java code above does.
// PrintIndependenceDay.groovy
def calendar = Calendar.instance
calendar.with {
clear()
set MONTH, JULY
set DATE, 4
set YEAR, 1776
println time
}
Wow. That is a good bit cleaner than what we started with. Part of the reason for that is we were able to get rid of all of those "calendar." prefixes. What allowed us to do that is calling the "with" method on the calendar object and passing a closure as an argument. What we have done there is establish a context that says "do all of this stuff with this calendar object". When the closure executes, the calendar is given an opportunity to respond to method calls like clear() and set() and the implicit call to getTime() when referring to the "time" property which is being passed to println. Likewise, the references to MONTH, JULY, DATE and YEAR properties are also being handled by the calendar object.
That is pretty slick. Lets dig just a little deeper to get a little better understanding of what is really going on.
Groovy closures have a delegate associated with them. The delegate is given an opportunity to respond to method calls which happen inside of the closure. Here is a simple example:
// define a closure
def myClosure = {
// call a method that does not exist
append 'Jeff'
append ' was here.'
}
// assign a delegate to the closure
def sb = new StringBuffer()
myClosure.delegate = sb
// execute the closure
myClosure()
assert 'Jeff was here.' == sb.toString()
When the closure is executed, those calls to append() in the closure end up being sent to the delegate, the StringBuffer in this case.
Something similar is happening in the Groovy calendar code above. A closure is being passed to the with() method. That closure is calling methods like set() and getTime() which don't really exist in that context. The reason those calls don't fail is the with() method is assigning a delegate to the closure before it is executed. The delegate being assigned is the object that the with() method was invoked on. In the calendar example, the delegate is the calendar object. Something like this is happening...
def closure = {
clear()
set MONTH, JULY
set DATE, 4
set YEAR, 1776
println time
}
def calendar = Calendar.instance
closure.delegate = calendar
closure()
This code does the same thing as the first Groovy example. Obviously the first one is cleaner.
I sort of lied a bit, or at least left out a detail that may be significant. The closure that is being passed to the with() method is really being cloned and it is the clone that is assigned the delegate and executed. This is a safer approach than monkeying with the original closure. If the reasons for that aren't clear, the explanation is another story.
Another bit of info that is missing here is the strategy that a closure uses to decide when to send method calls to the delegate. Each Groovy closure has a resolveStrategy associated with it. This property determines how/if the delegate comes in to play. The 4 possible values for the resolveStrategy are OWNER_FIRST, DELEGATE_FIRST, OWNER_ONLY and DELEGATE_ONLY (all constants defined in groovy.lang.Closure). The default is OWNER_FIRST. Consider the owner to be the "this" wherever the closure is defined. Here is a simple example...
class ResolutionTest {
def append(arg) {
println "you called the append method and passed ${arg}"
}
def doIt() {
def closure = {
append 'Jeff was here.'
}
def buffer = new StringBuffer()
closure.delegate = buffer
// the append method in this ResolutionTest
// will be called because resolveStrategy is
// OWNER_FIRST (the default)
closure()
// give the delegate first crack at method
// calls made inside the closure
closure.resolveStrategy = Closure.DELEGATE_FIRST
// the append method on buffer will
// be called because the delegate gets
// first crack at the call to append()
closure()
}
static void main(String[] a) {
new ResolutionTest().doIt()
}
}
So you see how the with() method helps establish a context where a bunch of things may happen "with" a specific object without having to refer to that object over and over. This can help clean up code like the Java code we started with. This approach can also be really useful when building a domain specific language in Groovy, a topic for another time.
Enjoy! :)
Posted by Jeff Brown at 9:39 PM 120 comments
Grails Training In Chicago Monday, August 04, 2008
We are really excited to have a 3 day Groovy/Grails training event coming up in Chicago later this month. The training dates are August 26-28. The training will be held at the Hotel Indigo in Palatine.
This is 3 days of lecture and reinforcing lab work. Attendees should expect to write a lot of Groovy and Grails code with your training expert. There is no better way to quickly get your team up to speed on the technology, well beyond the basics.
As with all G2One training events, students will receive a free 12 month license to use IntelliJ IDEA. The IntelliJ guys have done a fantastic job of building first class Groovy and Grails support for the IDE.
For a full course outline and more information, please visit http://g2one.com/training/. Any questions may be directed to training@g2one.com.
Posted by Jeff Brown at 11:39 AM 9 comments
G2One QuickCast Site Launched! Wednesday, July 30, 2008
G2One have launched the G2One QuickCast site. A G2One QuickCast is fast and furious little movie demonstrating something interesting about the Groovy language and/or the Grails framework.
The first movie available there demonstrates how powerful tools like Grails and Git can work together to support a really really agile development process. Watch this movie and try to do something like this with your web framework and your VCS. If you can't, your tools are not flexible enough. :)
Enjoy!
Posted by Jeff Brown at 9:56 AM 13 comments