views:

56

answers:

3

I’ve punted on this before, and/or hacked around it, but I’d like to solve it properly once and for all.

The question is what to do if I need a URL that changes per environment in a JavaScript module that's part of a Groovy/Grails project

For example, I have a JavaScript module that contains this function:

function init() {
    dojox.cometd.init('http://localhost:8082/grails-cometd/cometd');   // This URL changes for prod vs dev 
    dojox.cometd.subscribe('/queue/advisoryLock', onMessage);
}

grails link tags, etc, don’t work here. Is there a proper Grails/Java way of doing this? I couldn’t find anything…

+4  A: 

I know neither Java nor Grails, so there may be some native way I don't know about (which would obviously be preferable.), but one common way of dealing with this would be to define a global variable in the HTML document before the scripts are embedded:

<html>
<head>

<script type="text/javascript">
my_project_webroot = "http://localhost:8082";
</script>

... now embed your JavaScript files .....

you can then address my_project_webroot in functions:

function init() {
    dojox.cometd.init(my_project_webroot+'/grails-cometd/cometd');   // This URL changes for prod vs dev 
    dojox.cometd.subscribe('/queue/advisoryLock', onMessage);
}

if you find global variables ugly (they are), you could also consider setting up a global config object for all such settings (web root / static web root / current language...) to reduce clutter.

Also, the Dojo framework might to offer some configuration object that you could extend.

Pekka
For Grails, this meansmy_project_webroot = '<g:resource absolute="true" dir="/" />';The url this line creates is the url in grails.serverURL in Config.groovy.If you don't want the trailing slash, you can omit the dir attribute.
rlovtang
There's also the possibility to init the my_project_webroot variable from window.location.href, and strip everything after the first or second slash, depending on if you want to keep the context path or not. Only problem is if you deploy as ROOT on server, and run with a context path locally, then this must be handled differently.
rlovtang
@rlovtang good idea!
Pekka
+3  A: 

since grails supports configuration setting, I would specify the URL based on the environment and then set the value on the grails layout that you are using.

Same as above, but taking advantage of what grails gives you

inside configuration file

environments {
    development {
        env.root.url = 'http://localhost:8080/development'
    }  
    production {
        env.root.url = 'http://localhost:8080/production'
    }  
    staging {
        env.root.url = 'http://localhost:8080/staging'
    }  
}

inside the layout file

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<%@ page import="org.codehaus.groovy.grails.commons.ConfigurationHolder" %>
<html>
<head>
    <script type="text/javascript">
    my_project_webroot = "${ConfigurationHolder.config.env.root.url}";
    </script>

... now embed your JavaScript files .....

Also, depending on how your javascript files are structured, you could just embed the grails configuration values directly

Aaron Saunders
or instead of the import/access class directly, use ${grailsApplication.config.env.root.url}
Steven Sproat
I would prefer this way, it's the cleanest.
DaDaDom
Better to use the <tt>grails.serverURL</tt> setting, as it's a standard one. Documented briefly in section 3.1.1 of the user guide.
Peter Ledbrook
+1  A: 

There's also a Grails JavaScript URL Mappings plugin that will make some of the g.createLink functionality available on the client side to JavaScript. If you're trying to do links back to your own server.

John Stoneham