Grails – Error creating URL for parameters – UnsupportedEncodingException

Recently (with Grails 2.4.2) an exception popped up in the logs

Caused by: org.codehaus.groovy.grails.web.servlet.mvc.exceptions.ControllerExecutionException: 
Error creating URL for parameters [{language=en, id=256, controller=gallery, action=ajaxLoadMoreDesigns}], 
problem encoding URL part [en]: 'UTF-8'
..
Caused by: java.io.UnsupportedEncodingException: 'UTF-8'
        at java.net.URLEncoder.encode(URLEncoder.java:215)
        ... 9 more

for which there was not really an explanation/fix around google. Looking twice, it turns out the quotes (around UTF-8) are the problem causing the encoding lookup to fail. The exception is caused in RegexUrlMapping.groovy which in the end gets the encoding from the request in ApplicationTagLib.groovy:

String generatedLink = linkGenerator.link(urlAttrs, request.characterEncoding)

It’s easily reproduced like this:

import groovyx.net.http.RESTClient

def client = new RESTClient("http://localhost:8080")
client.get(path: '/', headers: ['Content-Type': "text/xml; charset='UTF-8'"]) //quotes around charset here

And there’s also an easy workaround – clean up the encoding in a Grails filter:

//workaround for some browsers/clients sending quoted encoding values which breaks link generation
if (request.characterEncoding) {
   request.characterEncoding = request.characterEncoding.replace("'", "").replace("\"", "")
}
Posted in Uncategorized | Leave a comment

Grails: Fix functional tests for forked execution

If you’ve also run into the issue that functional tests have a problem with forked execution, but you still want to use it for development (e.g. for reloading), you can use the environment support in BuildConfig.groovy for enabling forking for development mode, but disabling it in test mode (because the server running for the functional test mode is, despite test mode, still executed with the fork.run configuration).

forkConfig = [maxMemory: 1024, minMemory: 64, debug: false, maxPerm: 256]
grails.project.fork = [
        //fork during development for reloading, but for functional tests forked execution breaks the server start
        run: (grails.util.Environment.current == grails.util.Environment.DEVELOPMENT ? forkConfig: false)
]

Posted in Software | Leave a comment

Upgrade from Grails 2.2.2 to 2.4.1

Here’s what was necessary for me to upgrade handful of Grails projects to 2.4.1:

  • Change the grails.version in application.properties
  • grails clean is your friend when changing dependencies
  • change hibernate, tomcat and resources plugin versions to latest
  • kick out the spock plugin and the grails-spock dependency as these come now with Grails
  • the package of Spock’s IntegrationSpec changed and needs adaptation
  • use the applicationContext.xml and web.xml from a fresh 2.4.1 Grails project (be sure to merge in any custom modifications you have)
  • some older plugins we use have not been updated to remove use of the deprecated classes ApplicationHolder, PluginManagerHolder, ConfigurationHolder that were completely removed in 2.4 – this can be fixed by copying those removed classes into your project so they are there again
  • HTTP method restrictions are also checked in unit tests now, so the correct HTTP method needs to be set in tests
  • Anonymous classes caused obscure exceptions (java.lang.NoSuchFieldError this$0, java.lang.VerifyError) in some places – replacing the anonymous class with a closure fixed this problem – this is most likely a Groovy issue
  • tripped over a bug in startGrails.bat – on Windows the file.encoding system property was not set anymore (see GRAILS-11534)
  • upgrade to 2.4.2 was necessary later because of a bug in JSON serialization GRAILS-11513
  • An exception “Cannot create a session after the response has been committed” was fixed by rearranging the code that accessed the session
  • needed to adapt some corner case transaction handling code – this is likely caused by the Spring changes introduced by the newer Spring version
  • GrailsDomainBinder.getMapping was changed from a static method to instance method – easily fixed by just creating an instance
  • Played around with forked execution – we’ll use it for development mode, but not for the tests because of problems with the Geb functional tests
  • Support for the old databinding (with grails.databinding.useSpringBinder = true) doesn’t really work in tests
    • In unit tests the old databinding doesn’t work because the setting isn’t picked up – moving the affected tests to integration tests fixes this
    • dateCreated (which we manually set in some tests) isn’t bound by the setProperties databinding anymore – assigning dateCreated manually works as a workaround
    • the old databinding with setProperties doesn’t work for functional tests in some places – when used in Bootstrap.groovy the legacy databinding setting is not picked up – with constructor databinding it works, but not with setProperties
  • (change local Grails version and Grails version on CI server)
  • somehow when running in production, we needed to add additional dependencies, because missing classes caused ClassNotFoundExceptions. The required dependencies are runtime ‘org.springframework:spring-expression:4.0.5.RELEASE’ and
    runtime ‘org.springframework:spring-aop:4.0.5.RELEASE’

So all in all, the upgrade was not entirely smooth, but all problems could be solved.

Posted in Software | 12 Comments

Setting up a Ubuntu VM with Vagrant and Ansible on Windows

As Ansible has no out-of-the-box support for running on Windows, there’s some tweaking to do.

Please note that these instructions just run Ansible against a vagrant managed VM, no Vagrant Ansible provisioning is involved.

You’ll install cygwin (+ some packages for it), Vagrant (plus you need a VM software, the instructions assume VirtualBox) and Ansible

  • Install Vagrant locally, add to Path
  • Follow the installation instructions on this useful blog entry, leave out the Eclipse specifics if you don’t need them. You’ll need to adapt the vagrantfile example to use another VM provider if you’re not using VirtualBox
  • Get a Ubuntu box for Vagrant, e.g. this one here
  • Use this box in the Vagrant file from the installation instructions, be sure to use a file:/// prefix for the local box url.
  • At this point, you can already “vagrant up” in the directory where the vagrant file is located, and “vagrant ssh” into the machine you’ve created (user vagrant, password the same). You can also ssh from cygwin with “ssh vagrant@127.0.0.1 -p 2222”
  • In order to configure your Ansible hosts, create a “ansibleHosts” file in the directory where you’re working with Ansible, and add the following
    [local]
    127.0.0.1
    
  • To configure the vagrant ssh port (which is 2222), create a file “ansible.cfg” with the contents
    [defaults]
    remote_port = 2222
    
  • In order for Ansible to ssh into the VM, you’ll want to set up ssh keys. In cygwin execute “keygen -t rsa”, which creates a public/private key pair
  • Deploy the ssh key to your VM by running “ssh-copy-id -i /home/YOURUSER/.ssh/id_rsa.pub vagrant@127.0.0.1 -p 2222”
  • Create a Ansible playbook, e.g. this one here, it connects to the specified hosts (local from the ansibleHosts file earlier) and installs the phantomjs package (via sudo):
    - hosts: local
      remote_user: vagrant
      sudo: true
      tasks:
        - apt: pkg=phantomjs state=present
    
  • run the playbook with “ansible-playbook -i ansibleHosts playbook.yml” (which runs the playbook file using the Ansible hosts specified in ansibleHosts file)

Update: after some usage, it seems there’s some non-deterministic problems with SSH which stops the process in-between sometimes – broken pipes and the likes – so running Ansible with cygwin under Windows is (as of now, with this setup) not really production-ready. Better spin up (another) a Linux VM and use Ansible from there.

Posted in Software | Leave a comment

Grails – “Error An error occurred loading the grails-app/conf/BuildConfig.groovy file: null”

If you get this error, check if there’s another (wrong) groovy version on your classpath.

For me this happened in IntelliJ because I had @Grab’ed a third party library that depended on an older groovy version, and IntelliJ adds @Grab’ed dependencies if you have the “Add –classpath …” checkbox in the launch config checked.

Posted in Software | Leave a comment