Groovy 1.0 RC2 was released today. If all goes well over the next few days the 1.0 release should be available by year's end. The community has been waiting a long time for this. All of the hard work and patience from the Groovy development team is about to pay off. Thanks Guys!
Have A Groovy Christmas!
Groovy 1.0 RC2 Released Saturday, December 23, 2006
Posted by Jeff Brown at 2:48 PM 2 comments
The Definitive Guide To Grails Saturday, November 25, 2006
The Definitive Guide To Grails is finally available from Apress. The book is a well written easy read that provides a great foundation for Grails developers.
Manning's Groovy In Action (GINA) has been available through their Early Access Program for several months now. The final version of GINA will be available in the next month or so.
Things are heating up in the Groovy and Grails communities. Look for a lot of exciting things to be happening around Grails soon.
Posted by Jeff Brown at 9:03 AM 0 comments
Grails 0.3 Released Thursday, November 09, 2006
Grails 0.3 was released today. A lot of work went in to this release which addresses over 100 bugs and feature requests. In my opinion, the fact that Grails is currently at 0.3 is a little misleading. The framework is very powerful and stable. There is a lot on the horizon but the tool is very powerful in its current state. Give it a spin.
I have recently joined the Grails development team and I am looking forward to what the future has in store for Grails.
Posted by Jeff Brown at 9:34 PM 0 comments
Grails Support For HTTP Method Restrictions Saturday, November 04, 2006
I have committed code to Grails to support a declarative syntax for imposing restrictions on which controller actions may be invoked using which http request methods. See the docs for details.
Posted by Jeff Brown at 10:57 AM 0 comments
Grails Enhancement Submitted Saturday, October 21, 2006
I have worked up an enhancement to Grails recently that provides an easy declarative way for application authors to limit access to certain controller actions based on the http request method (PUT, POST, GET, etc...). Generally speaking, applications should not allow destructive operations to be initiated in response to a GET. That isn't the only reason to want to impose restrictions, but it is a common one. With Grails, the only way to deal with this is to put code in your controller to inspect the request object and figure out if the request was a GET, POST or whatever. For the common case where all I want to do is prevent certain actions from being invoked via a GET, I don't want to have to do that. I just want to tell the framework not to allow it. The patch I have worked up does just that. The patch allows code like this in your controller...
class EmployeeController {
// action1 may be invoked via a POST
// action2 has no restrictions
// action3 may be invoked via a POST or DELETE
def httpMethodRestrictions = [action1:'POST',
action3:['POST', 'DELETE']]
def = action1 { ... }
def = action2 { ... }
def = action3 { ... }
}
The patch has been attached to http://jira.codehaus.org/browse/GRAILS-379.
Posted by Jeff Brown at 3:24 PM 0 comments
Grails Presentation Thursday Evening Saturday, September 16, 2006
My Grails presentation Thursday evening went very well. Weiqi Gao blogged about the presentation in real time.
The presentation slides are available at http://www.ociweb.com/javasig/knowledgebase/2006-09/. The tone of the whole session was very light and fun. You will see in the notes that I included quotes about Grails from famous people such as John Lennon, Mr. T, Batman and Robin and even Elvis Presley. Each time a celebrity came up in the slides I asked a trivia question about that celebrity and the first person to shout out the correct answer was given a copy of the Groovy In Action MEAP, courtesy of Manning Publishing. Thanks to Manning for those.
There are not many code samples in the presentation slides. During the presentation I built a simple application and along the way applied the concepts that are mentioned in the notes.
Before the presentation there was some discussion among the group about the future of Java and a lot of people in the group agreed that dynamic languages are going to be an important part of what we do in the future.
Posted by Jeff Brown at 9:02 AM 0 comments
Learning New Languages, Like Haskell (not Eddie) Wednesday, September 06, 2006
There are a number of reasons for developers to learn new programming languages. One reason is to keep their skills current. Another reason is that many developers simply find learning new languages to be fun. Another reason is that learning new languages forces developers to think about problems differently. That is what I want to discuss.
Learning new spoken languages changes the way people think about problems. Learning new programming languages is no different. When a C++ developer learns Java they can't do pointer arithmetic any more. They can't use multiple inheritance in the same way. What about Ruby and Groovy? The fire marshall is going to shut down the Ruby bandwagon because it is way over capacity right now. I don't think there are any Java developers left who haven't at least tinkered with Ruby. Java developers learn Ruby and then realize things about Java that start to seem fundamentally wrong. Why isn't there a simple syntax in Java for declaring properties like you can in Ruby or Groovy? Why are there so many 1 line getters and setters in the Java world? What about that dynamic typing? That takes some getting used to. On and on... More languages... More examples...
Languages like C++, Java, Ruby and Groovy are all very different languages but at the same time, are all pretty much the same. They are all object oriented. When you write a program in one of those languages you model the business objects, encapsulate logic, pass references around and all of these objects collaborate to solve a problem. OO has been around for a pretty long time now and is an effective way to build systems. If learning different OO languages is beneficial (and it is), what about learning fundamentally different languages? That ought to be valuable as well. I say it is anyway.
I recently spent a little time playing with BF. That is interesting stuff but no sane person is every going to propose that is a good way to write anything. However, learning BF is an interesting exercise. Try to write a simple calculator in BF and you will be forced to think about things differently. Learning BF is strictly an academic exercise.
On a more practical front I have been playing with Haskell lately and am finding it very interesting. Haskell is a functional programming language. Functional programming languages are all about the function. Haskell is a real programming language that is used to build real systems, not just a goofy language to play around with (like BF). At first the language may seem prohibitively useless for its lack of things imperative programmers are used to. For example, there is no destructive assignment in a pure functional language. That means there is no such thing as "x = x + 1". What? How can I write software without basic functionality like that? You can. This "feature" isn't missing from the language (or whole class of languages), it just isn't necessary.
My Haskell Kung Fu is nowhere near sharp enough to provide any kind of tutorial but I will tempt your curiosity with some very basic hello world kind of examples. Take a look at this...
fac 1 = 1
fac x = x * fac(x - 1)
That is a way to write a function in Haskell to calculate factorials. The first line says "factorial 1 is equal to 1". The second line says "factorial of any other number is that number multiplied by the factorial of 1 less than that number". That seems pretty straightforward, doesn't it? If you read those 2 lines of code out loud, it reads almost like you would describe what a factorial is.
If you can follow the factorial example, the fibonacci example below shouldn't be difficult to understand...
fib 0 = 0
fib 1 = 1
fib x = fib(x - 1) + fib(x - 2)
I don't know how functional programmers really think about that but my OO mind thinks of that as 3 overloaded versions of the "fib" function. One takes a 0 as an argument, one takes a 1 as an argument and the other takes any other number as an argument. This could be written in haskell with just 1 function and some "if" blocks but the code above is "the functional way".
A slightly more complicated example is a sort routine like this...
my_sort [] = []
my_sort (x:xs) = my_sort less_than_x ++ [x] ++ my_sort greater_than_x
where
less_than_x = filter (<x) xs
greater_than_x = filter (>=x) xs
The first line there says that the result of sorting an empty list is an empty list. That seems reasonable to me. The rest is another "overloaded" (probably not the terminology the functional crowd would use) version of the same function. This version accepts a list as an argument where x is the first element in the list and xs is the rest of the list. That little syntax turns out to be useful a lot. The result of sorting that list is achieved by concatenating (++) 3 things. The first thing is a sorted copy of everything that is less than x. The second thing in the concatenation is x. The third thing in the concatenation is a sorted copy of everything that is greater than x (actually greater than or equal to x, as we'll see shortly). The labels "less_than_x" and "greather_than_x" are just that, labels. There is no Haskell magic at play there. The lines after the "where" clause define what those labels refer to. "less_than_x" is defined to be everything in xs that is less than x. "greater_than_x" is defined to be everything in xs that is greater than or equal to x. Since "less_than_x" and "greater_than_x" need to be sorted before the concatenation takes place, recursion is taking place.
Some may look at that code and immediately conclude that it is confusing to look at and can't possibly be a good way to write code. However, once you understand how each of those pieces work, this is really a pretty direct expression of what is being accomplished.
Maybe you will take some time to look at Haskell and find a lot of interesting things about it. If you are really feeling funky and want to explore functional programming constructs in Java, take a look at FunctionalJ. That is interesting to think about but I think from the perspective of tweaking your brain a bit, for a lot of folks learning Haskell is probably a more interesting and more valuable experience.
Enjoy!
Posted by Jeff Brown at 8:19 PM 2 comments
Obscure Programming Language Sunday, August 20, 2006
I was doing some research on quines this weekend and while doing so I stumbled across several obscure programming languages that I was not previously familiar with. The following is actual code I wrote that will compile and run (it isn't a quine)...
>++++++++++[>+++++++>+++++++++++>+++++++
+++>++++++++++++>+++>++++++++[<]>-]>-.>+
++++.>-.+++++.---.>-.>++.>-.<<<---.++++.
<++.--.>---.--.<+.>++++++++.<-----.-.>>>+.
Do you know what language that is? A few hints...
- The language is composed of just 8 commands, each expressed with a single character (7 are used in the program above)
- Whitespace is insignificant
- The language is "Turing-Complete"
- The language has a colorful name (if you reply to this, you may use the initials to avoid the offensive word)
Posted by Jeff Brown at 6:40 PM 7 comments
db4o and Groovy Saturday, July 08, 2006
I want to say thanks to Christof and the rest of the gang at db4o as they were kind enough to send me a hardcover copy of The Definitive Guide to db4o. The book showed up this week. I have not had time to read all of it at this point but at a glance it looks like the authors have covered a lot of interesting territory inlcuding replication with Hibernate, which I expect is going to be a big win for db4o in the eyes of a lot of folks.
I have worked up some interesting Groovy integration capabilities for db4o. As soon as I have some time to clean some of that up and get it documented I will be sharing that.
I wish continued success to all of the guys at db4o.
Posted by Jeff Brown at 9:42 PM 3 comments
New Groovy Spec Lead Wednesday, June 14, 2006
Today the official announcement was made that Guillaume Laforge is the new Groovy JSR-241 Spec lead.
The whole Groovy community is anxious about the next few months hoping that 1.0 will be finished up. Congrats and good luck to Guillaume!
Posted by Jeff Brown at 9:11 PM 1 comments
Groovy And JScience Sunday, June 04, 2006
I have been spending a lot of time investigating Groovy lately. I wanted to dig in to writing a Groovy Category so I started writing some code to support things like this...
def duration = 30.minutes + 2.hours
Before I got too far along there I discovered that John Wilson had already implemented a lot of that in his TimeCategory which is part of Google Data Support.
I had recently read a JNB article that Lance Finney had written on JScience and that gave me another idea. I decided to write a Groovy Category that would use JScience to support things like this...
def len = 2.kilometers + 500.meters
Since I wanted to do this as an exercise I decided to not even do any research to find out if anyone had already implemented something like this. I wanted to build this for my own benefit as a learning exercise. I started by expressing some of my own requirements in the form of a Groovy Unit Test like this...
class JScienceTest extends GroovyTestCase {
void testConversions() {
use(JScienceCategory) {
def len = 2.kilometers
assertEquals 2.0, len.kilometers, 0.00001
assertEquals 2.0E3, len.meters, 0.00001
assertEquals 2.0E5, len.centimeters, 0.00001
assertEquals 2.0E6, len.millimeters, 0.00001
assertEquals 2.0E9, len.micrometers, 0.00001
assertEquals 2.0E12, len.nanometers, 0.00001
def len2 = 400.centimeters
assertEquals 4.0E-3, len2.kilometers, 0.00001
assertEquals 4.0, len2.meters, 0.00001
assertEquals 4.0E2, len2.centimeters, 0.00001
assertEquals 4.0E3, len2.millimeters, 0.00001
assertEquals 4.0E6, len2.micrometers, 0.00001
assertEquals 4.0E9, len2.nanometers, 0.00001
}
}
void testAddition() {
use(JScienceCategory) {
def len = 2.kilometers + 500.meters
assertEquals 2.5, len.kilometers, 0.00001
}
}
void testSubtraction() {
use(JScienceCategory) {
def len = 3.kilometers - 500.meters
assertEquals 2.5, len.kilometers, 0.00001
}
}
void testMultiplication() {
use(JScienceCategory) {
def len = 3.kilometers * 2
assertEquals 6.0, len.kilometers, 0.00001
}
}
void testDivision() {
use(JScienceCategory) {
def len = 42.meters / 3
assertEquals 14.0, len.meters, 0.00001
}
}
}
My Groovy Kung Fu is still developing and I had not done anything at all with JScience before this. Even with those limitations I was able to get all of those tests passing in about an an hour.
Would you rather do this in Java...
Measure length = Measure.valueOf(50, SI.CENTI(SI.METER)).plus(Measure.valueOf(25.0, SI.METER));
Measure lengthInCentimeters = length.to(SI.CENTI(SI.METER));
System.out.println("length in centimeters is " + lengthInCentimeters.getEstimatedValue());
Or do this in Groovy...
def length = 50.centimeters + 25.meters
println "length in centimeters is ${length.centimeters}"
Isn't Groovy fun? :)
Posted by Jeff Brown at 4:42 PM 1 comments
Operator Overloading In Groovy Tuesday, May 30, 2006
I have been doing some Groovy development lately. I just spent a few minutes spinning around a quirky behavior that makes perfect sense to me now but at first had me scratching my head. Take a look at this...
def sqlDate = new java.sql.Date(System.currentTimeMillis())
sqlDate += 2
That code is creating an instance of java.sql.Date and adding 2 days to it. My moment of confusion comes from the fact that after adding the 2 days the sqlDate reference no longer points to a java.sql.Date object but instead points to a java.util.Date object. Hmm... What is going on?
The operator overloading is being inherited into java.sql.Date from java.util.Date. The plus method in java.util.Date is returning a java.util.Date, which makes perfect sense. Since that method is inherited into java.sql.Date and not overridden then when it is invoked it returns a java.util.Date.
Try this...
def sqlDate = new java.sql.Date(System.currentTimeMillis())
println sqlDate.class
sqlDate += 2
println sqlDate.class
Posted by Jeff Brown at 9:08 PM 7 comments