Thursday, September 28, 2017

Grails Development FAQ

Updated October 10, 2017

This is a growing list of frequently asked questions (FAQ) that I encounter teaching Groovy & Grails, with an eye toward Ellucian Banner XE Self-Service development. While many of these questions are Grails specific, a few pertain to the JetBrains IntelliJ Idea IDE that I use in class. Check back to see if the list has grown bigger:
  1. Can I open multiple projects in the same window in IntelliJ?
  2. Why doesn’t my Grails classrecompile and reload in the development server?
  3. Changes to my controller and domain classes compile and work. So, why do I get random errors in the run window, often a NullPointerException, sometimes related to scaffolding?
  4. I already have the browser open on the application page that I want, how do I stop IntelliJ from launching a new page for the application if I restart the development server?
  5. Hibernate with the H2 database writes an awful lot of log messages to the Grails console!
  6. If I use respond in the controller, where is the model data in the view?
  7. Where is the model data? I can’t find it when I dump out the request in the GSP!
  8. If I create a new domain instance from the params map, the id property is not set! And, the same thing happens if I try to copy the properties from one domain object to another. What is happening?
  9. Do I need to convert a string id from the params map to an integer before using get?
  10. How do I fix the Grails SDK? It changes every time someone checks in the project!
  11. I change the Grails SDK, and now IntelliJ Idea says that Groovy is not configured!
  12. null id in ... entry (don't flush the Session after an exception occurs)
  13. Why does saving a new domain object flush database changes?
  14. On a Mac I can't see ~/.sdkman to get to the Groovy or Grails SDKs?


Can I open multiple projects in the same window in IntelliJ?

  • No. The current versions of IntelliJ only allow one project per instance of the application.

Why doesn’t my Grails class recompile and reload in the development server?

  1. There are spaces in the path name; Spring Loaded doesn’t like spaces in the path.
  2. The class is in an ignored package; Spring Loaded has a fixed list of packages that it ignores: http://blog.askjoelit.com/2017/09/banner-9grails-25-development-problems.html.

Changes to my controller and domain classes compile and work. So, why do I get random errors in the run window, often a NullPointerException, sometimes related to scaffolding?


I already have the browser open on the application page that I want, how do I stop IntelliJ from launching a new page for the application if I restart the development server?

  • Edit the run configuration and uncheck “Launch browser.”

Hibernate with the H2 database writes an awful lot of log messages to the Grails console!

  • Most of this is at the Trace level in H2, but SQL statements are at the Debug level. Disable this in Config.groovy. Commenting out debug or trace in the log4j property will disable them; the same entries in log4j.main do not control anything.

If I use respond in the controller, where is the model data in the view?

  • Up to Grails 2.5.6 how the model object is names for a view is not defined in the documentation for respond. The scaffolding documentation incorrectly says it will be the <propertyName>Instance or <propertyName>InstanceList, but it doesn’t use the property name, it uses the data type. So,  a Course object becomes “courseInstance,” a list of Courses becomes “courseInstanceList,” and an array of Courses (Course[] courses) becomes “courseInstanceArray.” List<Course> courses becomes courseInstanceList.

Where is the model data? I can’t find it when I dump out the request in the GSP!

  • While you can use the request object to get the model data, the get<Something> method is actually defined to delegate the request the pageScope object. pageScope is also where variables defined in the GSP go. You can dump all the names with pageScope.getVariableNames().

If I create a new domain instance from the params map, the id property is not set! And, the same thing happens if I try to copy the properties from one domain object to another. What is happening?

  • The id property is not a property of the domain class, so the default constructor ignores it and doesn’t set it from the params map. It is a property provided by the metaclass, so it has to be set manually.
  • The same is also true if you assign from the properties of one domain object into another.
  • However: if you construct the domain object by defining it as the expected parameter of the controller action, the code behind that will set the id properly!

Do I need to convert a string id from the params map to an integer before using get?

  • No. The get method will convert the data passed to it if it can

How do I fix the Grails SDK in IntelliJ Idea? It changes every time someone checks in the the project!

  • The Grails SDK location is recorded in the IntelliJ project settings, in the file workspace.xml. Changing it is simple; right-click on the project and choose Grails -> Configure Grails SDK.
  • When doing Grails development with a a group, and using a repository or sharing projects by copying folders, the Grails location needs to be the same on every computer used for development. This is especially difficult if there is a computer-wide location for Grails and a mix of Microsoft Windows, Apple MacOS, and Linux development computers. In that case, if you use a Grails location in the user home directory, IntelliJ will record it as a path relative to the current user working on the project (not the user who set it). This can be simplified by using SDKMAN to manage the copy of Grails, but there is an issue that you must fix if you mix in Microsoft Windows computers, see http://blog.askjoelit.com/2017/10/normalizing-sdkman-across-development.html.

I change the Grails SDK, and now IntelliJ Idea says that Groovy is not configured!

  • Changing the Grails SDK may cause the project to drop the configuration for Groovy, since each Grails SDK has its own version of Groovy. Fix this by right-clicking on the project in IntelliJ, and selecting Add Frameworks Support. Scroll down the list on the left and select Groovy.

null id in ... entry (don't flush the Session after an exception occurs)

  • But an exception didn't occur! Except for this one about flushing after an exception... The most likely cause is to invoke a transactional service method (like a property validator) from a database operation inserting a new record (like save) in a non-transactional controller method. Hibernate becomes confused because the transaction ends without the new object being inserted into the database. It has to perform the insert afterward inside the non-transactional controller method. The best solution is to disable transactions for individual service methods that do not use the database with @NotTransactional, or disable transactions for all of the service methods if none of them access the database with static transactional = false. If you choose to use @NotTransactional on specific methods then make sure the service class is annotated with @Transactional, or the first @NotTransactional method will turn off transactions for the whole class.

Why does saving a new domain object flush database changes?

  • The Grails documentation says it does not, and hibernate actually is not flushing, but it appears to. The thing is that hibernate can do a lot locally without changing the database, like merge a domain object back into its context. In that case the merged record is not actually updated in the database until a flush happens. But other times it has to change the database to complete a step, like actually inserting a new record in order to get a generated id when it is an identity column. So it did not actually "flush," but it did have to make the database do something. Now here is the kicker: if the save is in a controller method and not inside a transaction, the insert statement sticks in the database as if it were flushed. If the save is in a transaction, a rollback can still reverse it.

On a Mac I can't see ~/.sdkman to get to the Groovy or Grails SDKs?

  • In the open file dialog on the Mac when you are selecting the SDK you can use Command+Shift+. to show or hide the folders and filenames that begin with a period.

No comments:

Post a Comment