Showing posts with label Grails. Show all posts
Showing posts with label Grails. Show all posts

Thursday, August 20, 2009

Choking on Java

As you can tell from my blog I am a long time Java developer who likes to flirt with dynamic languages. Not surprisingly my two favorite languages at this point are Groovy and Ruby. Therefore, I enjoy working with the Grails and Rails frameworks. After working with Java for so long I was starting to get tunnel vision around a single language. After all, Java is a general-purpose language that can do anything if you bend it enough.

However, Java is not always the best solution for all situations. Obviously, Web development is one of those glaring areas where Java can work but might not be the best candidate. I began developing web applications with Java using plain old servlets and jsp pages. Like most Java developers I also discovered Struts 1. While some of the components of the framework seemed a little strange, Struts was better than my homegrown attempt. So I developed with Struts for a while but I was not entirely satisfied. Of course there were other issues to tackle outside of the presentation layer including persistence, transaction handling, and other services. So I evaluated JDO, EJB, and Hibernate. I finally settled on Hibernate but there was still a mess between my presentation tier and my persistence layer. Later I found Spring and glued everything together. After evaluating countless presentation frameworks I refined my Java Web stack over time using Stripes, Spring, and Hibernate. This combination took a lot of experimentation but I was able to make Java conform to the web in a relatively lightweight manner. The point is that I had to do a lot of bending here.

When Rails first came on the scene I was fairly closed minded mainly because of my investment in Java. How could this newcomer trump all my hard work or be as robust as Java? Well after taking Rails out for a test drive I quickly realized how over-architected Web development was with Java. It reminded me of so many early math classes where it would take several pages of computation to achieve a result. Then more advanced math classes introduced techniques to achieve the same results in just a few steps. I appreciated the simplicity of solving a problem with less computation and yielding the same results (or better). Doing less work for the same results once I understand the underlying theory works for me.

But with RoR there was a fair bit of voodoo so I became less intrigued by Rails and wanted to know as much as possible about Ruby. Ruby turned out to be a fun language with constructs that are currently not available or easy to achieve with Java (i.e. closures, better mixin techniques, creating your own DSLs with builders, everything is an object, etc). I quickly realized that I could code much more expressively and achieve the same functionality with a lot less lines of code. Testing my code with a dynamic language instead of Java was also enjoyable because it was simpler. I actually wanted to do testing! Exposure to a new language like Ruby actually improved my Java code (and made me resent how noisy Java is). So now I am an aspiring polyglot with an open mind to new languages.

Not long after I looked at Rails I saw that Grails 0.3 was available (I think I first saw it on http://java.net). So the Java camp was attempting to answer Rails with Grails. OK fine, I took a look at Grails and this is when I was first exposed to Groovy. Groovy offered much of the same dynamic capabilities as Ruby and worked well with my existing Java code (mostly). And Grails offered much of the same convention over configuration principles like Rails. Even better I could integrate my Grails application with my existing Java code. It was like winning the World Series of Poker when I hooked up my existing Spring beans and Hibernate annotated domain objects with Grails. Grails automatically recognized my Spring beans and seamlessly added all of the GORM dynamic methods to my domain classes.

However, I still liked the Ruby language slightly better than Groovy because it did not carry the Java baggage along with it. So now I have a language and a framework that are great for new development, but I could not reach out to my existing Java classes or external libraries with Ruby. Then I found JRuby. JRuby allows me to write Ruby code and integrate with my Java code, Spring beans, etc. However, if I was going to use Rails and wanted to follow their paint by numbers framework then I was stuck with ActiveRecord. Also Rails does not have a service layer concept so my Spring beans did not naturally fit in the Rails framework. I quickly found out how to create a Spring bean factory in JRuby so my Rails controllers could access these services.

As much as I like JRuby there are some things that I want. First, I would like to see JRuby continue to strive for near Java performance. I do realize that we are talking about a dynamic language but I believe that this can be achieved. Second, I think that JRuby needs to provide easier integration for popular open source frameworks like Spring and Hibernate. Why shouldn’t JRuby/Rails emulate Grails the same way that Grails “borrowed” from Rails. Maybe the JRuby team could offer these items as gems to supplement the Rails framework. Or maybe this will be a pluggable feature with Rails 3? This is about bridging the gap between the Java and Ruby communities. Finally, I want to see Engine Yard offer commercial support and training for JRuby (which seem inevitable now that Charles Nutter is at EY).

While building Rails applications is fun, deployment can be a pain. I think that the leveraging JRuby/Rails on a Java platform makes a lot of sense here. Ruby contains several gems for integrating your Rails application in a Java environment. First, there is the Warbler gem, which allows you to take your Rails application and package it up in a standard war file format. So now your Rails application can be deployed on any standard Java container. Second, there is a Glassfish gem for deploying your applications without Warbler. The JDBC-ActiveRecord gem allows you to use your JDBC drivers to connect to your database instead of the Rails drivers. By deploying your Rails application on a JVM you get extra benefits like simpler deployment strategies, better threading support, and easier ways to scale. So while you might want Rails for development, the JVM might offer better services for housing your application. Even if you don't have to integrate any Java code you should still consider JRuby for Rails development IMHO.

So, if you choose to use a dynamic language should you use Grails or Rails for Web development? I do not think there is a cut and dry answer to this question. In this case, the lines are a little blurry because the underlying languages seem to be converging in capabilities. However, I will provide my 2 cents on this issue and watch the comments for this entry fill up. Let me start off by saying that I like both frameworks for different reasons.

Let's start with Grails. Grails is great for Java developers that have existing experience with Spring and Hibernate. The migration to Grails will benefit these people the most because they understand how Spring and Hibernate work. Grails is pretty much just a wrapper around these frameworks so when problems arise they will have the same issues that had to be solved before. The benefit is that this is a great way to get started with a dynamic language (like Groovy) and start to understand what all the fuss is about using a familiar set of tools. Plus, as I indicated earlier you could drop in your Spring beans and Hibernate classes and watch them work out of the box. You will need a deep understanding of Spring and Hibernate when things go wrong to troubleshoot problems as they arise. This is where things might break down for developers that do not understand these frameworks.

Now let's talk about Ruby on Rails with JRuby. Working in Rails is just a fun way to develop. Rails was created solely to solve the domain specific problem around web development. And Rails developers seem to introduce easy solutions to mundane problems. There are lots of plugins and gems that can make Rails even more enjoyable. However, there are thousands of Java libraries available that you might want or need to integrate with. As a Rails developer why wouldn't you at least give yourself the option to tap into those libraries?

So how does everybody win? I believe that everyone will benefit if these two communities come together. I have observed the Java and Ruby communities for some time and seen a lot of mud thrown from both sides. At the end of the day you have to ask yourself why these two groups cannot see that they really need each other at some level. Is this more of a cultural gap than a technical one? Java is infused into so many organizations and is not likely to go away any time soon. What better way to get your Rails application deployed in a Java shop than making a case with JRuby? Also, if you want to evangelize and strengthen Rails as a popular development platform why not build on top of one of the largest existing infrastructures? Rails will only survive by gaining acceptance as a viable framework.

As for Java developers that think that Rails is not a good solution for Web development I say they are passing judgment without entertaining the idea. Let's face it, Java is legacy. If you still think that JSF provides rapid development or think WebSphere is a great application server then you probably will not buy into this blog entry. As technologists we need to find and accept better ways to solve problems. Maybe Rails is not the end all solution for Web development. There are many emerging frameworks like Seaside, Django, Lift, Sinatra, Camping and more that believe they have a better mousetrap. This is a sign that people believe that Java is too complicated and over-architected for web development.

Let me summarize by overstating how much Web development has changed. Java developers and Ruby developers need to understand how the JVM can benefit them. Web development using domain specific languages and dynamic languages are hot and over architected Java solutions are not. But there is a middle ground and whether you choose Grails, RoR, or some other framework to simplify your web development you are probably on the right track. Finally, both the Java community and the Ruby community have things to offer each other to secure their survival.

Well off to look at more Scala...

Tuesday, January 20, 2009

Grails Pitfalls and Tips

I have worked with Grails for some time now and thought I would share some of the common mistakes I have made early on. I also thought I could discuss some things that can make developing with Grails easier. Here is my short list of items:

Zero Turnaround Time

One of the convenient features of Grails is the ability to make a change and have that change be available immediately in your application. This is an obvious time saver and allows you to be more productive while developing your application. However, there are times when you will make major refactoring changes on the fly that the JVM cannot deal with. An example of this might be when you introduce something new in the middle of an existing class hierarchy. While it may appear that Grails is happy and your environment is sailing along you might see odd behaviour in the application and see some strange runtime exceptions along the way. What usually remedies this situation is instructing Grails to rebuild the internal structures in your application. This can be done by executing the following command and restarting your application:

# grails clean

Grails Console

One tool that you will want to keep in your Grails toolkit is the Grails console. This allows you to run a your application in an enviroment so you can experiment with code on the fly. One of the main reasons I do this is to try out my unit and integration code in the console before, or during, writing my tests. This is a fast way to get confidence that your test code will provide the results you want. And because you are doing this in the console you do not have to keep executing the grails test-app command to reinitialize the environment.

Since you have the full environment in the Grails console you can easily get references to your Spring beans and services. You are automatically provided a reference to the org.codehaus.groovy.grails.commons.spring.GrailsWebApplicationContext class with a variable named ctx. This allows you to do things like this in the Grails console:

def service = ctx.bookStoreService
def book = service.getCurrentBook()
println "The most recent book is ${book.name} by ${book.author}"
println book.dump()
You can see all of the defined beans that Grails is aware of like this:

ctx.beanDefinitionNames.sort().each {println it}

Manually Assigning Primary Keys

Most of the time your domain objects will have autogenerated primary key values for the id field. However, I ran into a situation where I needed to manually assign a primary keys for one of my domain objects. This took a little bit of trial and error to make this work. Here is how you do this correctly:

          
String id
static mapping = {
id generator:'assigned', column:'RECORD_ID', type:'string'
}

Also note that you must set the id manually outside of the object constructor on a separate line like this:

def obj = new MyDomainObject(name:'whatever')
obj.id = 'REC000001'
obj.save(flush:true)

Not like this:

def obj = new MyDomainObjects(name:'whatever', id:'REC000001')
obj.save(flush:true)

because the value will not be saved.

Manually Triggering Quartz Jobs in Grails

Grails has an excellent plugin for managing scheduled Quartz jobs. However, I had a situation where I wanted to manually schedule a job. I could not find this in the documentation so after poking around in the source I figured out how to do this using the following technique. First you have to define the job name and group like this:

class MyValidationJob {

def name = 'MyJobName'
def group = 'MyGroup'

// your executable job method here...
}

Then you can manually trigger the job like this:

          // trigger the job manually by job name and group from your controller/service/whatever
def quartzScheduler // inject this in your class
quartzScheduler.triggerJob("MyJobName", "MyGroup")

Using Packages in the Grails

Grails provides a directory structure for your application components by convention similar to Rails. However, this can cause issues if you put your classes directly inside of these folders because they seen by Java in the default package. Using the default package can cause you issues when compiling your classes. Since we are using Groovy (and really Java) it is my opinion that you should add packages to your Groovy classes. I also think that modules in Ruby translate better than package structures at this point but we are stuck with Java constraints.

You can add packages to the provided services and domain folders and Grails will make Spring beans out of them. You just need to be careful not to use the same name for the bean twice. You just reference the bean by the name of the class. For example let's say you have a service called com.myco.service.validation.MyValidationService. Grails will expose this as a bean reference named myValidationService.


Base Classes with GORM

It is common practice that developers make a base domain class with common features of your subclassed domain objects. By defining an abstract class you can define common properties for your domain objects. There is a catch however. The GORM DSL allows you to define constraints and mappings blocks in these classes for validation purposes and defining ORM mappings respectively. The current problem is that if your subclasses have their own mappings and/or constraints defined they will override what is in your superclass instead of being merged with the superclass blocks. I am hoping that a future version of Grails addresses this issue (1.1 hopefully).


Unexpected NPEs

One of the earliest mistakes I made when working with Grails was generating NullPointerExceptions without much to decipher in the stack trace. The most common problem for me (which you will overcome quickly) was to make sure you validate your domain objects and handle the errors appropriately in your controllers. The errors object is automatically added to your domain objects and can be checked with the hasErrors method on those objects.


Viewing the Source of your GSP Files

This is just a quick tip that allows you to view the generated source of you GSP files. This is a simple as adding the 'showSource' parameter to your URL like this:

http://localhost/yourapp/yourController/list?sort=dateCreated&max=20&showSource

Monday, September 8, 2008

Generating GORM Domain Classes

I am on a project that already had a legacy database in place with about 100 tables. I did not want to create my GORM domain classes manually for my Grails project. I am surprised that I did not find any existing code to handle this code generation so I created a Groovy script to handle this. I am sure this code could use some improvements such as handling more SQL types so I will just call it a 0.1 release because it does what I needed for now. Modify the sql varible so it has the right database connection information. Also, modify the tables hash so you can control which domain classes to generate based on a [tableName:className] structure.

   1  import groovy.sql.Sql
2 import java.sql.Types
3
4 sql = Sql.newInstance("jdbc:mysql://localhost:3306/pts_development",
5 "root",
6 "password",
7 "com.mysql.jdbc.Driver")
8
9 // tables hash format => table : className
10 tables = ['PTS_REG_DTL':'Detail','PTS_REG_MST':'Master']
11 tables.each { table, className ->
12 File file = new File("${className}.groovy")
13 sb = new StringBuilder()
14
15 fieldNames = []
16 fieldTypes = []
17
18 query = "select * from ${table}"
19 sql.query(query.toString()){ rs ->
20
21 sb << "class ${className} {\n"
22
23 def meta = rs.metaData
24 if(meta.columnCount <=0) return
25
26 for(i in 1..meta.columnCount){
27
28 fieldName = meta.getColumnName(i).toLowerCase().replaceAll(/_[\w]/,{ it[1].toUpperCase()})
29 fieldNames << fieldName
30 fieldType = ""
31
32 switch(meta.getColumnType(i)) {
33 case Types.BIGINT:
34 fieldType = "Long"
35 break
36 case [Types.BINARY, Types.BIT, Types.BOOLEAN, Types.SMALLINT]:
37 fieldType = "Boolean"
38 break
39 case [Types.CHAR, Types.VARCHAR]:
40 fieldType = "String"
41 break
42 case [Types.DATE, Types.TIMESTAMP]:
43 fieldType = "Date"
44 break
45 case [Types.DECIMAL, Types.FLOAT]:
46 fieldType = "Decimal"
47 break
48 case [Types.INTEGER, Types.NUMERIC]:
49 fieldType = "Integer"
50 break
51 default:
52 fieldType = "Object"
53 }
54 fieldTypes << fieldType
55 sb << "\t${fieldType} ${fieldName}\n"
56 }
57
58 // Print out the table mappings
59 sb << "\tstatic mapping = {\n"
60 sb << "\t\ttable '${table.toString()}'\n"
61
62 for(j in 1..meta.columnCount) {
63 sb << "\t\t${fieldNames[j-1]} column:'${meta.getColumnName(j)}'\n"
64 }
65 sb << "\t}\n"
66
67 // Print out the table constraints
68 sb << "\tstatic constraints = {\n"
69
70 for(k in 1..meta.columnCount) {
71 sb << "\t\t${fieldNames[k-1]}("
72 sb << "nullable:${meta.isNullable(k) ? 'true': 'false'}"
73
74 if(fieldTypes[k] == 'String') {
75 sb << ", maxSize:${meta.getColumnDisplaySize(k)}"
76 }
77 sb << ")\n"
78 }
79 sb << "\t }\n"
80 sb << "}\n"
81 }
82 file.write(sb.toString())
83 }

This code will generate a separate file for each domain class you specified in the tables hash in the current directory. Just make sure you have your database jar file in your classpath. Here is how you could run this code from the command line:

groovy -cp .:/Users/meagle/java/api/mysql-connector-java-5.0.4/mysql-connector-java-5.0.4-bin.jar GormGenerator.groovy

Friday, August 15, 2008

Securing a Grails application with Acegi and Crowd (Revisited)

I recently had a need to combine these technologies to provide authentication and authorization with Crowd in my Grails application. I ran across a very good article that handholds you through this process. You can reference the original aricle here.

However, I ran into several issue when I tried to apply the configuration in the article. The original article uses Grails 1.0.1, the Acegi Security Plugin v0.2, and Crowd 1.3. When I attempted to follow the instructions I attempted to use Grails 1.0.3, the Acegi Security Plugin v0.3, and Crowd 1.4. If you are still reading then make sure that you continue to use 0.2.1 version of the plugin because the Crowd integration module has not been updated to reference the latest Acegi/Spring Security framework updates such as pack naming. From here I will reference where you will need to make modifications for each step that requires it in the original article.

Step 1: Grails & Acegi Installation

Again, use the Acegi Security Plugin v0.2.1

Step 2: Create Grails Application with Acegi Security

Download and install the Acegi Security Plugin v0.2.1 in your Grails project.

Step 3: Crowd Download

Download Crowd v.1.4.4 from the Atlassian website.

Step 4: Crowd Installation & Configuration

The installation and configuration is surprisingly as easy as the original author suggests. Just follow the installation instructions.

Step 5: Grails + Acegi + Crowd Integration

Make absolutely sure that you do not skip the step regarding crowd.properties. If the application name and password do not match the same values in the application configuration you will not be allowed to attempt authentication against Crowd. You can setup these values in the Crowd administration console by navigating to the Applications tab and selecting the application from the list. From there click the Details tab and ensure the name and password are set to the same values as crowd.properties. Also, make sure that the application.login.url value is modified to the correct login url. The one specified in the article should be consistent with the example.

I did follow the author's lead and copied the applicationContext-CrowdClient.xml file from the
CROWD_HOME/client/crowd-integration-client-1.4.4.jar file and positioned it in the ACEGI_APP/conf/spring/ directory and then renamed the file to resources.xml.

The modifications I had to make to resources.xml were different from the author's article. Here are the beans I added:

   1  <bean id="crowdUserDetailsService" class="com.atlassian.crowd.integration.acegi.user.CrowdUserDetailsServiceImpl">
2 <property name="authenticationManager" ref="crowdAuthenticationManager"/>
3 <property name="groupMembershipManager" ref="crowdGroupMembershipManager"/>
4 <property name="userManager" ref="crowdUserManager"/>
5 <!--<property name="authorityPrefix" value="ROLE_"/>-->
6 <property name="authorityPrefix" value=""/>
7 </bean>
8
9 <bean id="crowdAuthenticationProvider" class="com.atlassian.crowd.integration.acegi.CrowdAuthenticationProvider">
10 <property name="userDetailsService" ref="crowdUserDetailsService"/>
11 <property name="authenticationManager" ref="crowdAuthenticationManager"/>
12 <property name="httpAuthenticator" ref="httpAuthenticator"/>
13 </bean>
14
15 <bean id="crowdLogoutHandler" class="com.atlassian.crowd.integration.acegi.CrowdLogoutHandler">
16 <property name="httpAuthenticator" ref="httpAuthenticator"/>
17 </bean>
18
19 <bean id="logoutFilter" class="org.acegisecurity.ui.logout.LogoutFilter">
20 <constructor-arg value="/"/>
21 <constructor-arg>
22 <list>
23 <ref bean="crowdLogoutHandler"/>
24 <bean class="org.acegisecurity.ui.logout.SecurityContextLogoutHandler"/>
25 </list>
26 </constructor-arg>
27 <property name="filterProcessesUrl" value="/j_acegi_logout"/>
28 </bean>
29
30 <bean id="filterChainProxy" class="org.acegisecurity.util.FilterChainProxy">
31 <property name="filterInvocationDefinitionSource">
32 <value>
33 CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
34 PATTERN_TYPE_APACHE_ANT
35 /images/**=#NONE#
36 /scripts/**=#NONE#
37 /styles/**=#NONE#
38 /**=httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,securityContextHolderAwareRequestFilter,rememberMeProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
39 </value>
40 </property>
41 </bean>

AcegiGrailsPlugin.groovy


Instead of making this modification to this file I put the change inside of resources.xml. If you make this modificaiton inside the plugin code and you upgrade it you will need to remember this. Instead Grails will override the authenticationManager in AcegiGrailsPlugin with this definition inside of resources.xml:

   1      <bean id="authenticationManager" class="org.acegisecurity.providers.ProviderManager">
2 <property name="providers">
3 <list>
4 <ref local="crowdAuthenticationProvider"/>
5 <ref bean="anonymousAuthenticationProvider"/>
6 <ref bean="rememberMeAuthenticationProvider"/>
7 </list>
8 </property>
9 </bean>

Friday, January 18, 2008

Migrating to Grails?

The last time I looked at Grails it was around version 0.4. Now that we are approaching a 1.0 release I wanted to see how much further the Grails team has advanced. I wanted to start by using my existing Spring and Hibernate components from my Java project (I am currently using Stripes for our presentation layer). Benefits for doing this might include:
  • Abstracting your Java domain model and services so they are not coupled to Grails.

  • The ability to continue using your Java services and model objects outside of Web applications or have the ability to integrate with other Web presentation frameworks.

  • A migration path to Groovy if you want to rid yourself of straight Java altogether. I am sure that there would be massive redux in LOC. For me it was experimenting with the intersection of my experiences with Rails and Java Web development.

Does this mean that if you reuse your Hibernate Java domain objects you do not get all of the GORM features like (order.save())? No, your domain objects transparently take full advantage of the mixed in methods in Grails. You might find that the services you are reusing from Spring are mostly passthroughs to DAO that you do not need anymore because of GORM. Here is a trivial example showing how to use a Grails controller to use existing Spring services to perform DAO operations and how to use your Hibernate domain objects directly as GORM objects:


UserService userService  // This is injected in via auto-wiring

def index = {

// Using Java Services
def user = userService.find(1, User.class)
println user.firstName
user.firstName = 'Mark'
userService.save user
println User.get(1).firstName

// Using strait Grails
user = User.get(1)
println user.firstName
user.firstName = 'Phil'
user.save()
println User.get(1).firstName
}

Here is how we took our annotated Hiberate classes so Grails would recognize them:

Edit your hibernate.cfg.xml file in the GRAILS_APP/grails_app/conf/hibernate directory and add your domain objects:

<!DOCTYPE hibernate-configuration SYSTEM
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<mapping class="com.meagle.common.bo.Address" />
<mapping class="com.meagle.common.bo.User" />
</session-factory>
</hibernate-configuration>
In your DataSource.groovy configuration file add the configClass line to your datasource configuration so your annotated Hibernate classes will be recognized by Grails:
dataSource {
pooled = false
driverClassName = "com.ibm.db2.jcc.DB2Driver"
username = "meagle"
password = "******"
configClass
=org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsAnnotationConfiguration.class
}
Here is how you expose your existing Spring beans to your Grails application:
  1. Edit your GRAILS_APP/grails_app/conf/spring/resources.xml file and add the following line:
    <import resource="applicationContext-core.xml"/>
    This tells Grails to include your Spring resources (We put our Spring config file in the same directory as the resources.xml file).

  2. Make sure all of your Spring and Hibernate domain objects written in Java are on the classpath. We put ours in a jar file in the GRAILS_APP/lib directory.

One gotcha here to remember is that your Spring configuration file should not include any definition to a SessionFactory and your services and DAOs that reference a SessionFactory needs to be the name "sessionFactory". Otherwise, you will end up with multiple session factory objects which is probably not what you want.

Overall I am very impressed with Grails at this point and would challenge Java developers to take a serious look at this framework. If you are fortunate enough to have IntelliJ 7 then there is decent plugin support for building Grails applications.