Tuesday, September 5, 2017

Banner 9/Grails 2.5 Development Problems and Resolutions

This is a page of random problems and solutions encountered using Grails 2.5 for Ellucian Banner XE (9) Self-Service development. As new problems are resolved, they will be added to this list.

20170902 Grails Throws a NullPointerException on Recompile & Reload

After a file is changed, such as a controller, Grails notices the change, recompiles, and reloads the file but throws an error similar to this: ERROR plugins.AbstractGrailsPluginManager  - Plugin [controllers:2.5.0] could not reload changes to file.

This problem has only appeared for me on Microsoft Windows systems: when a class is recompiled and reloaded, a NullPointerException is thrown, often by the AbstractGrailsPluginManager. The class is actually recompiled and reloaded, so it was not clear exactly what the problem was. Sometimes the error originates in the scaffolding system, even when the application does use scaffolding. There are plenty of comments around the Internet about disabling forked execution, but only one comment clarified why.

Grails 2.3 added forked execution to launch the development server. All that means is that versions before that ran both the Grails command and the development server in the same JVM. Starting with 2.3, the Grails command launches a second JVM for the development server. The most obvious reason is that the development server has more resources available, and that could mean a lot to a resource-strapped application. A full explanation can be found on the Grails website here: http://grails.io/post/43484836985/road-to-grails-23-forked-execution.

It sounds fancy, but what it means is that the Grails app under development is running in one JVM while the Grails core itself is running in another. Major reasons given are to provide more resources for the application by putting it in its own container, prevent Grails classes from being visible to the application because of a shared CLASSPATH, and reduce conflicts between meta-classes.

The downside is that for some reason on Microsoft Windows changing a class causes an onChange event in both JVMs triggering an update. Unfortunately the launching JVM does not have the required sub-system that the application does, and that causes the NullPointerException. Only one person commented on this as the real reason, and I found that comment on a message board at http://grails.1312388.n4.nabble.com/Grails-2-3-Resources-NullPointerException-td4648201.html.

It does explain that most of the suggested solutions involve disabling the forked execution in the BuildConfig.groovy file. All that needs to be done is to comment out the run definition in BuildConfig.groovy, in the section grails.project.fork, to change the model back to a single process:

grails.project.fork = [
    // configure settings for compilation JVM, note that if you alter the Groovy version forked compilation is required
    //  compile: [maxMemory: 256, minMemory: 64, debug: false, maxPerm: 256, daemon:true],

    // configure settings for the test-app JVM, uses the daemon by default
    test: [maxMemory: 768, minMemory: 64, debug: false, maxPerm: 256, daemon:true],
    // configure settings for the run-app JVM
//  run: [maxMemory: 768, minMemory: 64, debug: false, maxPerm: 256, forkReserve:false],
    // configure settings for the run-war JVM
    war: [maxMemory: 768, minMemory: 64, debug: false, maxPerm: 256, forkReserve:false],
    // configure settings for the Console UI JVM
    console: [maxMemory: 768, minMemory: 64, debug: false, maxPerm: 256]
]

While the error is annoying, the class does get recompiled and reloaded in the application correctly. The error can be ignored.

20170816 Classes Do Not Recompile or Reload

The package name is critical for getting classes to be recompiled and reloaded in the Grails development server. This was difficult to dig up, and while many people blame Grails the problem actually lies in Spring-Loaded. Mathi Fonseca figured it out over three years ago, but he is the only one who seems to explain the problem correctly.

The secret is in the Spring-Loaded definition. If you do not provide a package name when creating a class, The Grails create-? script will place it in the grails package, and that is one of the packages specifically excluded from recompilation by Spring-Loaded. Examining this at the source, the packages excluded have the following prefixes. It is quite an extensive list, and grails is just one package in the middle:
  • antlr.*
  • com.springsource.tcserver.*
  • groovy.*
  • groovyjarjarantlr.*
  • groovyjarjarasm.*
  • grails.*
  • java.*
  • javassist.*
  • javax.*
  • org.apache.*
  • org.aspectj.*
  • org.codehaus.groovy.*
  • org.h2.*
  • org.hibernate.*
  • org.hsqldb.*
  • org.object.asm.*
  • org.springframework.*
  • org.springsource.loaded.*
  • org.xml.*
Any classes put into any of these packages will fail to be recompiled and reloaded by the Grails development server.

20150910 JavaLaunchHelper has Multiple Definitions

This one shows up in Apple MacOS, but not in Windows. In Java 8 the class JavaLaunchHelper is implemented in both the JDK java command and in the libinstrument.dylib library. Since they both seem to be exactly the same, the message is just an annoyance that cannot be squelched.

No comments:

Post a Comment