Have you ever created a class manually in the right folder for what you needed. Then instead of going through grails create-integration-test package.Class, you just create a new class under /tests/integration/package. I have spent more time than I would like to admit trying to figure out why the test wouldn’t run as I named the class wrong.
Did you know there are reserved variable names? If you have a parameter in your controller called action. $action maps to the function in the controller that will be called. This can lead to no request getting to your controller.
Strings and GStrings
Make sure you understand the different types of Strings and their usage, only use the GString when it is needed.
Here are a few examples of String usage. In the first example, we use a regular single quote string, where if we added the GString it would not print the variable. In the second example, we have double quotes where we could potentially use the GString. And then in the last example we show the GString usage.
GSP’s allow you to put the code in scriptlets, but this can lead to issues. In my first Java project, we used scriptlets entirely too much. It was really just a procedural approach to doing Java looking back. We had tons of scriplets that called to Oracle PL/SQL procedures for all the heavy lifting. We were all new to Java and didn’t know any better. I learned a lot from our mistakes. Just because you can add a scriptlet doesn’t mean you should. I have avoided doing scriptlets in GSP’s for the same reason.
def is neat to use, but it can cause problems when we don’t type our code. Using def makes code harder to read and causes surprises at runtime. We should try to use get over findById, this was pointed out by Burt Beckwith in his talk entitled, “Little did he know”. Using get is a special query to retrieve one instance, where findById uses the dynamicFinder. Burt elaborates on how this is because of caching in Hibernate in this talk and how this can slower.
In your mapping for you domain class if you have a column that is the same name as the variable field itself you don’t need to specify it. So, instead of the first example you can just have the second piece of code. In this scenario, your database table would also have an ID and VERSION column as well.
GORM is a powerful tool for Grails developers. It tries to do a lot for you and sometimes can create problems. Grails validates using the constraints that you have defined in your domain class. If any values in the domain instance violate the constraints, the save will fail and the constraint errors will be attached to the domain instance. The trouble is, this failure to save the domain instance happens quietly: you won’t know about it unless you check the return value of save() or call hasErrors().
If you hope to truly be comfortable with GORM you need to understand what the session is and what impact it has on applications. A session is basically an in-memory cache of objects that are backed by a database. When you save a new domain instance, it is implicitly attached to the session, it is added to the cache and becomes a Hibernate-managed object.
If you are working with an existing database then you should set dbCreate to validate. If you don’t, GORM will add a version and id column. What validate will do on start up is validate the domain objects and database schema match instead of updating it. If they don’t, Grails won’t start.
Personally I was initially confused with the dynamic finders in GORM. I remember working on my first Grails project and looking all over for the methods. After working for many years as a Java developer who liked to debug through codebases to understand the code, I was amazed when the light bulb went off. In this example, you see the concept of dynamic finders.
A dynamic finder looks like a static method invocation, but the methods themselves don’t actually exist in any form at the code level. Instead, a method is auto-magically generated using code synthesis at runtime, based on the properties of a given class. Take for example the Book class. The Book class has properties such as title, releaseDate, and author. These can be used by the findBy and findAllBy methods in the form of “method expressions”.
Creating a Grails application to access an existing legacy database can be very challenging. As you create the domain classes and controllers and setup your database configuration make sure to pay close attention to your names, I have been known to fat finger these and waste a lot of time.
Sometimes you don’t want to mess around with checking the return value of every save() and you’d be more than happy if Grails were to throw an exception for validation failures. This isn’t the default behavior, but you can easily switch it on via a failOnError. Although when your code is ready to ship you need to turn it off and handle your exceptions. It can be better to use hasErrors() as you make your code production ready.
Collections are the natural way to model one-to-many relationships in an object-oriented language. GORM makes using them pretty easy considering what’s happening behind the scenes. Nonetheless, this is definitely one area where the impedance mismatch between object-oriented languages and relational databases raises its ugly head. It is important to remember that your in-memory data can be different than the database.
Learn the default values when dealing with your domain classes; lots of bloat can be avoided. In this example, since nullable is defaulted to false you don’t need to even put it in there.
What gotchas would you add?
Are there any that you think are not needed?
How do you help new members of the team deal with familiar gotchas in your codebase?