Showing posts with label Groovy. Show all posts
Showing posts with label Groovy. Show all posts

Friday, July 18, 2008

Getting closer

As I'm getting closer to finishing up the essential code for GrailsCrowd, I noticed that I'm doing on the fly refactorings more seamlessly than I was able to do when I first started hacking with Groovy/Grails. And Groovy Closures are my friends these days :-)

Here's a small example from the GrailsCrowd code base - 2 simple controller actions to query for Grails projects by tags, only with the difference that the first action gets all the projects within a system for a specified tag (globally) and the other one gets projects for a tag for a specific member. Both actions operate on the Tag instance, so I refactored the common functionality of querying for Tags into a method which takes a closure:


class GrailsProjectController {

...
private def withTag(callable) {
if (!params.selectedTag) {
redirect(uri: '/notAllowed')
}
def tag = Tag.findByName(params.selectedTag)
callable(tag)
}
...
}


And then the above mentioned actions became:


class GrailsProjectController {

...
def findByTagGlobally = {
def total = 0
def projects = []
withTag {tag ->
if (tag) {
total = Tagging.countByTag(tag)
//Using CrieteriaBuilder here, so we could query by 'taggings' association
projects = GrailsProject.createCriteria().list(params) {
taggings {
eq('tag', tag)
}
} //Criteria builder
//Sort by name since GrailsProject implements Comparable and the name property is its natural order
projects.sort()

} //if
} //Closure
render(view: 'list', model: [projects: projects, navMenu: 'discoverNavigationByTag',
paginatingController: controllerName, paginatingAction: actionName, total: total,
menuContext: [tag: params.selectedTag]])
}

def findByTagForMember = {
def total = 0
def projects = []
def member = Member.findByName(params._name)
withTag {tag ->
if (tag) {
if (!member) {
redirect(uri: '/notAllowed')
}
total = Tagging.countByTagAndMember(tag, member)
//Using CrieteriaBuilder here, so we could query by 'taggings' association
projects = GrailsProject.createCriteria().list(params) {
taggings {
eq('tag', tag)
eq('member', member)
}
} //Criteria builder
//Sort by name since GrailsProject implements Comparable and the name property is its natural order
projects.sort()
} //if
} //Closure
render(view: 'list', model: [projects: projects, navMenu: 'memberProjectsNavigationByTag',
paginatingController: controllerName, paginatingAction: actionName, total: total,
menuContext: [tag: params.selectedTag, member: member]])
}
...
}


Also notice the use of GORM CriteriaBuilder which allowed to nicely query m:n 'Tagging' association class!

Keep Groovying.

Later...

Saturday, June 7, 2008

Programming with closures

Recently I caught myself thinking that my programming habits are changing while programming in Groovy. In particular, I started using closures more and more to clean up my code, make it more DRYer, e.g. by not just merely using existing closures provided by libraries such as GDK, GORM, etc., but by creating my own closures.

Here's a small example from GrailsCrowd. The idea here is to either 'accept project participation invitation' or 'reject project participation invitation'. So, in the Controller, I factored out the common code of retrieving the Member, Project, redirecting to the appropriate action afterwards, etc. to a private method which takes a closure, and calling that closure for the actual action of 'acceptance' or 'rejection':


private def withProject(callable) {
def invitee = freshCurrentlyLoggedInMember()
def creator = Member.findByName(params.creator)
def project = GrailsProject.get(params.projectId)
//Call the closure
callable([project:project,creator:creator,invitee:invitee])
redirect(controller: 'mailbox')
}

def acceptParticipationInvitation = {
withProject {projectMap ->
projectMap.project.acknowlegeParticipationAcceptance(projectMap.creator,
projectMap.invitee, params.messageId.toLong())
}
}

def rejectParticipationInvitation = {
withProject {projectMap ->
projectMap.project.rejectParticipationInvitation(projectMap.creator,
projectMap.invitee, params.messageId.toLong())
}
}


IMO, this makes code cleaner, reusable, and more maintainable. Also, this style of programming with closures kind of replaces good old Template Method design pattern.

Keep on Groovying, folks!

Later...

Tuesday, April 15, 2008

Access RESTful API in 2 LOC

Today I was playing with json-lib and FriendFeed API in Groovy console and was able to fetch feed's JSON representation and do a simple result filtering in 2 lines of code! So, for example, here are all my recent twitter entries (filtered from all the other content e.g. different services like flickr, amazon, etc.):


import net.sf.json.*

def friendFeedJsonResponse = new URL('http://friendfeed.com/api/feed/user/dima767').text
JSONObject.fromObject(friendFeedJsonResponse).entries.
findAll { it.service.id == 'twitter' }.
each { println it.title }
I know it is a very simple example, but IMO, with an 'expressiveness' and 'compactness' of Groovy, in the majority of cases, there is no need for a 'wrapper' library and various web APIs could be used 'as is'

Later...

Thursday, April 10, 2008

Grails in a 'Cloud'

These days, the new generation of computing, so called 'cloud computing', where the infrastructure of the entire data centers is outsourced, abstracted, and hosted somewhere in the 'cloud' (on the Internet), is getting hugely popular. In a nutshell, it provides a so called 'low barrier to entry' for smaller internet companies to make their presence on the Internet market place without spending a fortune and ridiculous amount of time and energy buying their own hardware and maintaining their own data centers.

Amazon EC2 service hugely popularized this type of computing and early this week, Google jumped on the bandwagon with their App Engine exposing the power of their computing infrastructure, as well as the entire web development stack (Python-based - what else did you expect from Google) :-) to the army of ordinary, but creative software development minds.

After the announcement, Google has received feedback from developers requesting support for different programming languages/frameworks, and among Perl and Ruby, the requests for Java/Groovy/Grails are overwhelming.

Now that we have a rock-solid RAD web framework for Java (Grails that is), we are just missing the last piece of the puzzle: a rock-solid and affordable Grails hosting in a 'cloud'. The demand seems to be there. Hint, hint for ambitious start up companies :-)

Later...

Friday, April 4, 2008

So enjoyable

While hacking GrailsCrowd today, I caught myself thinking that programming in Groovy is such an enjoyable experience (for me). Take this method for example:


// Social feature: gets a list of 'colleagues' working on the same projects as *this* member
def getProjectColleagues() {
getActiveProjects().collect
{it.participants}.flatten().findAll
{it.participant.id != this.id}.collect {it.participant}
}
Is it possible to navigate "deep" object graph and express the same intent with the similar compactness in 'raw' Java code? I think not :-)

Later...

Tuesday, February 12, 2008

Hidden gem: grails.war.resources

In the process of packaging up the Grails application as a WAR in preparation for deployment to Tomcat, I needed to figure out a way to exclude the Oracle JDBC drver from WEB-INF/lib (we use 'shared' Oracle driver for our web apps which gets loaded by the Catalina's common ClassLoader). So I was thinking of a way to provide an "event hook" script, and while reading Grails' War.groovy I found a "hidden gem". That is a closure which is defined in the application's Config.groovy. So when this closure is defined, the War.groovy calls it with "staging directory" as a parameter and sets Ant as its 'delegate' right before zipping it up as a war.

So I was able to do the following (... from Config.groovy):


//Closure to customize the packaging of a war. In particular it excludes the Oracle JDBC driver
//from the war as it is loaded by the Catalina common ClassLoader when deployed to Tomcat
grails.war.resources = {stagingDir ->
delete(file: "$stagingDir/WEB-INF/lib/ojdbc14-10.2.jar")
}

This is real nice, but I don't think this feature is documented anywhere.

Later...

Monday, February 11, 2008

Plugins for local needs

The Grails plugin system is great not only for creating all kinds of useful functionality available publicly, but also is a perfect framework to extract bits and pieces of reusable logic suitable only for internal corporate projects.

At our organization we started finally using Grails for internal projects. The first small web application was done in a matter of a few days. But then when it was time to package it up as a 'war', we had a little dilemma and that's where Grails plugin system came to the rescue.

In a nutshell, we use Spring Security (formerly known as ACEGI) together with JA-SIG Central Authentication Service, for all our auth/authz needs. For Grails applications, I did not choose Grails Acegi plugin as it does not seem to provide CAS authentication support (yet?). So we reverted back to good 'ol Spring resources.xml and dropped all the verbose Acegi bean definitions there (hopefully Spring Security 2 should reduce the 'configuration chaos' dramatically). Works just fine. But we have 3 "String" bean definitions there pertaining to CAS properties, such as 'casServiceUrlPrefix', 'casLoginUrl', and 'casValidateUrl'. So, for the typical Spring web app., we define those as JNDI-bound resources, like so:


<bean id="casServiceUrlPrefix" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName"><value>java:comp/env/casServiceUrlPrefix</value></property>
</bean>

<bean id="casLoginUrl" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName"><value>java:comp/env/casLoginUrl</value></property>
</bean>

<bean id="casValidateUrl" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName"><value>java:comp/env/casValidateUrl</value></property>
</bean>
So, when packaging application as a 'war' and deploying it to Tomcat, this is fine, but in the 'development' mode, in embedded Jetty, I would have liked to put this config somewhere else. Like conf/Config.groovy for example. That's where Grails plugin system came in, and with its wonderful SpringBeanBuilder I was able easily dynamically create those 3 bean definitions during assembly phase of the ApplicationContext, depending on the environment the application was running in.

Here's the plugin:


import grails.util.GrailsUtil as GU
import org.springframework.jndi.JndiObjectFactoryBean

class CasPropertiesResolverGrailsPlugin {
def version = 0.1
def author = "Dmitriy Kopylenko"
def title = "This plugin is used to provide cas related properties to the Spring beans used for Spring Security config"
def description = ''' The plugin participates in the creation phase of the Spring application context
which is used to configure Spring Security related beans and dynamically provides
'configuration beans' namely 'casServiceUrlPrefix', 'casLoginUrl', and 'casValidateUrl'
depending on the environment in which Grails application is preparing to run.

More specifically, if the environment is 'development' then the value is sourced from
Grails Config instance. On the other hand, if the environment is 'production', the value
is sourced from standard ess JNDI namespace.
'''

def dependsOn = [:]

def doWithSpring = {
switch (GU.environment) {
case 'development':
casServiceUrlPrefix(java.lang.String, application.config.casServiceUrlPrefix)
casLoginUrl(java.lang.String, application.config.casLoginUrl)
casValidateUrl(java.lang.String, application.config.casValidateUrl)
break
case 'production':
casServiceUrlPrefix(JndiObjectFactoryBean) {
jndiName = 'java:comp/env/casServiceUrlPrefix'
}
casLoginUrl(JndiObjectFactoryBean) {
jndiName = 'java:comp/env/casLoginUrl'
}
casValidateUrl(JndiObjectFactoryBean) {
jndiName = 'java:comp/env/casValidateUrl'
}
break
}
}
...

I'm sure there are other ways to do this, but that was fun nevertheless :-)

Later...

Tuesday, February 5, 2008

Grails 1.0 is golden!

Yes, after more than 2 years in the making, with the development team hard at work, the Grails 1.0 final has been officially released. IMO, this event is historical and a great milestone for "lightweight" web development on the JVM platform.

Happy Grails hacking!

Later...

Saturday, December 15, 2007

Fetch random GORM model

Despite busy schedule at work and a year old daughter at home, who now requires constant attention, I was able to get some time to work on the Grails community site (Grails Crowd).

As a part of it, I wanted to have a feature to display a 'random' user (a 'member') In fact, keep displaying a random user as long as 'Discover users' link is being clicked. You know, kind of like Flickr's "Explore" feature. So with a help of standard JDK library features i.e. 'java.utils.Collections.shuffle()' and Groovy closures, here's what I've come up with:

MemberController's action:


...

def findRandom = {
def member = null

withMemberIds { memberIds ->
//Pick the last one
member = Member.get(memberIds[-1])
//Then remove it from the list
memberIds.pop()
}

if(member) {
render(view: 'discover', model: [member: member])
}
else {
//No one is registered yet - just 'go home'
redirect(uri:'/')
}
}

private def withMemberIds(closure) {
def memberIds = session.memberIds
if (!memberIds) {
memberIds = Member.withCriteria {
projections {
property('id')
}
}
if (!memberIds.isEmpty()) {
//Some members are in the database:
//Shuffle 'em up
Collections.shuffle(memberIds)
session.memberIds = memberIds
}
else {
//No members are in the database
return
}
}
closure(memberIds)
if (memberIds.isEmpty()) {
session.memberIds == null
}
}

...



It works like a charm.

Later...

Friday, December 7, 2007

Why Grails is so 'close to home'

Here's another [big] reason why Grails is not a "foreign" technology for Java developers. I know, it's been said before, but this is a real world example of a Java person coming to Grails and experiencing this familiar state of things: 1) Create war; 2) Drop into any of the available Java Servlet container/app server 3) Sit back and relax (in the ideal world) :-)

I'm not sure if the same is true for JRuby (On Rails), so I'm not going to speculate here ;-)

Later...

Tuesday, October 9, 2007

Fun with tags

I've been playing with groovyconsole the other day to experiment with some 'tag' (yes, the web2.0 tags) :-) manipulations, etc. Let's say I wanted to build the del.icio.us style 'for:username' tag trickery, to send a message, save bookmark, etc. to any particular user's 'private inbox', etc. Extremely easy with Groovy:


tags = ['tag1', 'tag2','for:dima','tag4','for:someoneelse']

usersWhoShouldRecieveSomething = tags.findAll { it[0..3] == 'for:'}.collect { it - 'for:' }

assert usersWhoShouldRecieveSomething == ['dima','someoneelse']


Later...

Sunday, May 20, 2007

Could it be any easier?

Well here I am again, on the second week of development of my Grails based 'addictive time waster' web2.0 site (I'm not rushing and spend may be an hour a day on it). As I described in the previous post, I was having a blast with Grails custom codecs feature which enables adding various 'encoding/transformation' features to any arbitrary Java types with ease! Well, I'm continuing "abusing" custom codecs with a great level of success and most importantly with a lot of fun.

As I noticed on almost all of those user generated content web2.0 style sites, there are some kind of a 'Submitted by: user234 x days ago type of a piece of info. So, I've decided to add 'time ago' type of a stat to my web app. I'll continue to show the 'Submission' class for the examples, representing user's submission of any kind. So in order to track when Submissions are created, I've added a 'createdOn' property:


class Submission {

...
Date createdOn = new Date()
...
}


That will take care of recording the date of submission. Now, when retrieving and showing the the submissions, there would need to be some kind of a calculation to show the 'x minutes/hours/days/weeks/months/years ago' info. So, I've decided to "abuse" the codecs feature and "attach" the "encoding" of the date type into the 'time ago' string to the java.util.Date type. Thanks to the "richness" of the Joda time library, I was able to do that easily and put the code into the custom codec:


import org.joda.time.*

class TimeAgoStringCodec {

static encode = { date ->
def start = new DateTime(date)
def end = new DateTime(new Date())
def ago = Minutes.minutesBetween(start, end).getMinutes()
if(ago == 0) {
return 'less then 1 minute ago'
}
else if(ago < 60) {
return "$ago minute" + (ago > 1 ? "s ago" : " ago")
}

ago = Hours.hoursBetween(start, end).getHours()
if(ago < 24) {
return "$ago hour" + (ago > 1 ? "s ago" : " ago")
}
ago = Days.daysBetween(start, end).getDays()
if(ago < 7) {
return "$ago day" + (ago > 1 ? "s ago" : " ago")
}
ago = Weeks.weeksBetween(start, end).getWeeks()
if(ago < 4) {
return "$ago week" + (ago > 1 ? "s ago" : " ago")
}
ago = Months.monthsBetween(start, end).getMonths()
if(ago < 12) {
return "$ago month" + (ago > 1 ? "s ago" : " ago")
}
ago = Years.yearsBetween(start, end).getYears()
return "$ago year" + (ago > 1 ? "s ago" : " ago")
}
}


And equipped with this codec, I am then able to call: submission.createdOn.encodeAsTimeAgoString() and viola, I have the proper 'time ago' for any Date type application-wide!

Here I could conclude that adding 'codecs' to any arbitrary Java type application-wide is piece of cake in Grails, and also here is a great example of the advantage of Groovy's seamless integration with "raw Java" where I was able to make use of an existing Java library (Joda time) with zero integration overhead.

Later...

Sunday, May 13, 2007

Permalink codec

So, for about a week I've been working on my fun little "social" Grails web application and I've been having a lot of fun.

Yesterday, while jyting I've been taking a note of its URL structure. Let's say you have a claim, and then in order to see it, the URL to it is not something like http://jyte.com/claim/show/12345 , but rather more readable, like http://jyte.com/cl/dima767.myopenid.com-is-the-only-grails-hacker-on-jyte

That's called "permalink" (for permanent link) and is done by converting the text of the claim (or any user submition for that matter) into permalink string (removing all the special characters e.g. \W, and replacing them with '-'). Then permalink essentially becomes a searchable attribute of the submission, so instead of doing something like Claim.get(1234) you do Claim.findByPermalink(params.permalink). It's just a way of creating "user friendlier" interfaces.

Thanks to Grails and its nice custom URL mapping, and custom codecs facility, I was able to implement "permalink" functionality very easily!

Lets' say I have a domain class "Submission":


class Submission {
String title

//permalink property here is for nicer URLs
String permalink

}


So then I simply create "PermalinkCodec" utility class and place it in grails-app/utils so the Grails "ExpandoMetaClass" machinery could "weave" this functionality into all Strings!


class PermalinkCodec {

static encode = { str ->
str.toLowerCase().replaceAll(/\W/,'-')
}
}


Then in my "SubmissionController's" "save" action I do something like this:


...
def save = {
def s = new Submission()
s.properties = params
s.permalink = params.title.encodeAsPermalink()
s.save()
...
}


And finally, i define the custom mapping:


class MyAppUrlMappings {
static mappings = {
...
"/s/$permalink" {
controller = 'submission'
action = 'show'
}
...
}
}


So this will give users nice URLs like http://myapp/s/my-shiny-and-the-best-in-the-world-submission instead of http://myapp/submission/show/1234

I think it's a little thing, but nice, nevertheless.

Later...

Sunday, February 25, 2007

Groovy adoption continues

There are a lot of heated debates lately about Java vs dynamic languages such as Ruby and Groovy, the Ruby vs Groovy, RoR vs Grails, etc. Some folks say that Groovy is a failure, that it's a hacker's toy language and that it's much slower (cause it's doing all the wonderful meta object magic at runtime) than "raw" Java. Of course it's slower, but come on, we live in the 21st century and with the computing power available and type of work we do (for typical web applications, anyway) does it really matter? And of course, as we all might know, that the most time is spent in the database and passing data over the wire. After all, if one needs pure real time performance or builds aircraft management system, than yes, choose the right tool for the job i.e. real time C, Ada or even Assembly.

Anyway, I've got this new project assignment - it's a small and simple CRUD application with several screens backed by Oracle. I didn't choose Grails yet, as the DB schema is so twisted that it wouldn't map naturally to the domain. Instead I've decided to introduce some Groovy via Spring 2.0 dynamic language integration. I've written controllers, validators and repository in Groovy. Here's the code snippet from simple Spring controller implemented in Groovy:

class AvailableCourseSearchController extends AvailableCourseBaseController implements InitializingBean {

AvailableCourseRepository availableCourseRepository

public ModelAndView processFormSubmission(HttpServletRequest request, HttpServletResponse response,
Object command, BindException errors) throws Exception {
def availableCourses =
this.availableCourseRepository.findAllByCourse(
new Course(unitOfRegCode:request.getParameter('unitOfRegCode'),
offeringUnitCode:request.getParameter('offeringUnitCode'),
subjectCode:request.getParameter('subjectCode'),
courseId:request.getParameter('courseId')))

if (availableCourses.isEmpty()) {
errors.reject("courses.not.found")
return showForm(request, errors, getFormView())
}
def courseHolder = new CourseHolder('courses':availableCourses)
request.getSession().setAttribute(getCommandName(), courseHolder)
new ModelAndView(getSuccessView(), ['courseHolder':courseHolder,'suffixAList':suffixAList,'athleteCodeList':athleteCodeList])


And then the implementation of the course repository uses groovy.Sql to query and construct Course object. It's no JPA of course, but for simple case like this it works like a charm:

class AvailableCourseRepositoryImpl implements AvailableCourseRepository {

Sql db

void setDataSource(DataSource dataSource) {
this.db = new Sql(dataSource)
}


List findAllByCourse(Course criteria) {
def query = buildDynamicQueryString(criteria)
def courses = []
this.db.eachRow(query) { courseRow ->
courses << new Course('unitOfRegCode':courseRow.unit_of_reg_cd,
'offeringUnitCode':courseRow.offering_unit_cd,
'subjectCode':courseRow.subj_cd,
'courseId':courseRow.course_no,
'courseTitle':courseRow.course_title,
'suffixA':courseRow.suffix_a,
'unavailable':courseRow.course_deleted_ind == 'N'?false:true,
'required':courseRow.required_ind == 'N'?false:true,
'athleteCode':courseRow.athlete_cd,
'id':courseRow.id) }
return courses
}
}


This usage of Groovy in these simple scenarios proved to be simple and expressive. The next step is a full-blown Grails application!

Later...

Sunday, February 11, 2007

Groovy adoption begins

After virtually being in the Groovy and Grails world for a couple of months - that is reading GINA and Definitive guide to Grails books and just playing around with Grails, I finally decided to start slowly introducing this wonderful language and framework at work.

So I decided to "just do it". The first opportunity came as there is a need to rewrite a simple CRUD type of an application written in Oracle forms (BTW, this app is used by one person only one time a year) That would be the typical Spring stack app. At first one might think that it would be a perfect candidate for Grails, but then several factors decided against it: the db schema is so messed up that even "raw" Hibernate mapping would not be able to help (it doesn't have any PK for instance; tables are terribly denormalized... agrrr); and also I decided to wait until Grails matures a little, so I would have easier times of pushing it through our "red tape".

So I've just introduced a simple helper written in Groovy, using groovy.Sql to do a simple DB update. Then injected that Groovy implementation into a "raw" java DAO using Spring 2.0 dynamic language support. I'll tell you one thing - the clarity of the code is even better than using JdbcTemplate (Oops.. did I actually say it) :-)

Next step is to rewrite the SimpleFormControllers in Groovy to reduce the amount of code in half.

And then fully rewrite one of our simpler Spring apps (namely netid query) in Grails (shhh... don't tell anyone...I've already done it... When the time is right I'll introduce it to our crowd at work)

Later...

Wednesday, January 24, 2007

Philadelphia SPUG

Yesterday I went to the Philadelphia's Spring user group meeting with two of my colleagues, where Thomas Risberg presented "using Groovy with Spring" (using Spring 2 dynamic language support) and Jason Rudolph of Grails fame presented "An introduction to Grails"

Thomas showed the arbitrary Spring web app with Controller implemented in Groovy and seamlessly integrated with the rest of the app e.g. dependency injected, etc. This is really cool integration and I'm definitely going to explore it by slowly introducing some Groovy bits and pieces into our existing Spring apps by perhaps implementing some Services in Groovy (where it makes sense of course) to do things much more expressively and naturally :-) One such example would be the XML parsing (agrrrrr) with Groovy's excellent XML support i.e. XmlSlurper, GPath, etc.

Then Jason did an excellent job of introducing Grails to the audience. I felt that the presentation was very fresh, dynamic and not boring. Jason used a "live coding" demo, where he coded from scratch the basic "Racetrack" application (from his "Getting started with Grails book") before our eyes. Nice job Jason! I might even steal his presentation to do it at our internal "Design and Development" meeting to introduce it to our development crowd.

And also I've won a copy of an excellent and much anticipated "Groovy in Action" book! The only caveat is that I've ordered that book from Amazon a couple of weeks ago and it actually arrived last night :-( So this one will go to our "Development library" at work to educate other developers about this excellent language.

I am very excited about Groovy and Grails development and the growing momentum it has. And I sure hope to see Grails applications being developed and deployed at our enterprise some time in 2007!

Later...