Wednesday, December 29, 2010

Grails, configuration and the logSql option

I've tried today to make the dataSource.logSql configurable from an external file so that after deployment I can decide if I want to see the SQL statements in logs or not.

After a previous success with changing the dataSource.url parameter in a properties file designated as an external configuration file I did exactly the same with the logSql option. It turned out not to work.

However what did work was when I included not a ".properties" file but a ".groovy" file as the override configuration and then configured the dataSource as follows:
dataSource {
logSql = false // disable SQL statements logging
}

I've included the external configuration from the environments block like this:
// set per-environment serverURL stem for creating absolute links
environments {
production {
grails.config.locations = [ "file:/etc/example/example-config.groovy" ]
grails.serverURL = "http://www.changeme.com"
}
...

That did the trick so I've tried to go one step further and completely reconfigure the dataSource that previously used an embedded HSQL database to use MySQL:
dataSource {
logSql = false
driverClassName = 'com.mysql.jdbc.Driver'
dialect = 'org.hibernate.dialect.MySQL5InnoDBDialect'
dbCreate = 'update'
url = 'jdbc:mysql://127.0.0.1:3306/example'
username = 'root'
password = ....
}
Obviously since there's no MySQL JDBC driver in my application I've had to supply one to the common libraries folder in Tomcat (in Ubuntu if you install Tomcat via apt-get then the folder is /var/lib/tomcat6/common, otherwise it's just the lib folder in your tomcat installation) and all worked just perfectly :)

This is probably the best thing that ever happened to web application deployment :D This way you're able to completely reconfigure your application (even the most intimate things like bean properties if you so desire) and all that from as many configuration files as I want (just one works as well).

To utilize the new capabilities I've also reconfigured logging:
log4j = {
appenders {
file name: "application", file: "/var/example/log/example.log"
file name: "stacktrace", file: "/var/example/log/stacktrace.log"
}

debug application: 'grails.app'

(the rest of usual logging settings here...)
}
.
That's soooo cool that I can do that :) It helps me be in line with what the admin of our production environment demands.

And best of all: NO DAMN XML WHATSOEVER :) I love being a Grails developer :)

Tuesday, December 28, 2010

Grails and application.gsp layout - revisited

Hi there folks!

While I'm developing applications in Grails I always like to have good names for things I create. Controllers, domain objects, views... The only thing I couldn't find a good name for until now was application layout.

As you can imagine the names application.gsp or main.gsp seem like a perfect match for application-wide layouts. The problem with main.gsp is that it's already taken by the scaffolding mechanism and it's very unlikely that the whole application will be based on scaffolded views. The problem with application.gsp however is much more severe. Once you create this guy it'll apply to everything even if there's no layout specified. This also applies not only to views but to static resources as well! So before you go ahead and create the application.gsp file be prepared to what's coming on to you.

But (as usual with Grails) there's hope :) You can rename the global catch-all name of the layout to use for everything in the conf/Config.groovy file:
grails.sitemesh.default.layout = "none"

This way I've specified that the layout named none.gsp will be used as the catch-all instead of application.gsp and so I can use the latter one for my evil purposes :)

I hope this will save someone the headache I've had trying to figure this out, especially with the selenium plugin or partial-renderings from actions (like the ones used in Ajah) that when married with the original application.gsp looks just wrong all along.

Monday, December 27, 2010

Rails 3.0 - more like Grails :)

Hi there folks!

I can't quite shake the feeling that the new Ruby on Rails in version 3 is more like Grails than it was before :)

Previously everything you did was invoked within the project. There was a script folder that contained scripts to execute. server, generate those are only a few of the examples. In Grails it is different: you get a global command called grails that invokes scripts from either the scripts folder within your project or from a global folder. Well, the new RoR works exactly the same way :) There's a rails command that does exactly the same work :)

Secondly there is the problem with plugins (or gems as they are called in the Ruby world). Previously you just had to know which gems you needed to run the project which was up to the original project creator to document it. In Grails we've always had the appliaction.properties file listing all the required plugins in their respective versions. In RoR 3.0 there's a Gemfile file serving exactly the same purpose :)

Man I like seeing ideas being borrowed between opensource projects! This makes the landscape so much more difficult to choose wrong when selecting the proper platform to do the job!

Grails and dynamically generated JavaScript

Hi!

I can already hear you guys explaining in thousands of words why such a thing is inherently bad. I understand that, I even encourage others to do static JavaScript instead of dynamically generated because it is simply better this way. There are however times when having such a thing comes incredibly handy. When?

- whenever you need to pass on some dynamically-generated variables (like URLs for example) and you only want to do it once
- whenever the code depends on some configuration option

There are more examples but the general rule in my opinion is: as long as you keep your JavaScript generation marginal you're on the safe side.

Let's see how we can implement such a thing.

No doubt there's more than one option to do that. The way I've chosen is in my opinion best because it separates the actual program logic from the generation of JavaScript. So what I've done was I've created a separate controller, called ScriptsController, that has some actions on it (usually actions that provide configuration options for the static part of the JavaScript code)
class ScriptsController {
def home = { }
}
In this case there are no variables passed on from controller to the view but as you can imagine there are possibilities to do that.

I'm using the outcome of this view as
<script 
type="text/javascript"
src="${g.createLink(controller: 'script', action: 'home')}.js">
</script>
and instead of rendering plain HTML code from my GSP I'm rendering JavaScript from /views/scripts/home.js.gsp:
<%@ page contentType="text/javascript"%>
var HomeLink = "${g.createLink(controller: 'home', action: 'index')}";

Because I am a very lazy man and the situation where I need the same set of dynamically-generated content in different views for one controller I've decided to create a tag for it:
class ExampleTagLib {
static namespace = 'g'

def script = { attrs ->
def link = g.createLink(
controller: 'scripts',
action: attrs.name ?: controllerName)
out << """<script type="text/javascript" src="${link}.js"></script>"""
}
}
So here I ask for the current controller's name (which is btw nicely preprocessed by Grails) and use that instead of passing in the same parameter value every time I need it even if the dynamic portion is named the same as the controller that called it. A convention, so to speak.

So here's the simples usage example:
<g:script />
What this will do it will look-up the current controller name and render a script tag that will access the outcome of an action with the same name as the current controller as the src. This is exactly the same as the first version if called from HomeController only shorter.

If however you need to get the script breaking this convention (for whatever reason like common scripts maybe) then the name parameter comes in handy
<g:script name="common" />
This way the common script will be requested.

As usual here's a ready-to-use example.

I hope this will help you out to write less dynamically-generated JavaScript but when you'll have to do it your code will be better structured.

Monday, December 20, 2010

Grails 1.3.6, code-coverage and NTLM authentication error

Hi folks!

Edit on April 25th, 2011

Mike was kind enough to apply a hotfix that I made to the code-coverage plugin. This hotfix disables loading of external DTDs while processing cobertura.xml file. To that end if you're using this one and facing the issue described below you'll want to upgrade the plugin to version 1.2.3.

It's been a bad, bad day today, let me tell you. I'm still pissed off... but let's start from the beginning.

At first it's been great because the new Grails came out. New means better (and in fact it is better), new features - the usual stuff. Right up until you're forced to work behind an NTLM-protected proxy.

Well, first of all I'd like to point out that giving access to the Internet only via proxy is just asking for trouble. There's tons of apps simply not working from behind a proxy, especially one that needs authentication. Just take all Java applications working on Linux with nothing but the core runtime library and you'll know what I mean.

However up until the previous (1.3.5) version of Grails this problem has been overcomed by using Ivy that registered an NTLM authentication provider and all was just nice and dandy.

But in this version guys have upgraded to version 2.2 of Ivy which turned this feature off until Ivy is really in need to download something from the net. This means that if there's anything counting on proxy being setup correctly you're going to find yourself in deep sh..t.

There are 2 methods to overcome this problem:

1. Downgrade to Grails 1.3.5 (I'd recommend that unless like me you really need some of the new features that came to be in 1.3.6 like the "run-script" thingy - extra handy!!!)
2. Install a proxy server that can communicate with an up-stream NTLM-protected proxy

If you're counting on some bad-ass sites telling you to set the http.proxyUser and http.proxyPassword system settings to get it to work again please be adviced that it's just plain not true. This had been so ages ago, but now things are a lot more complicated and this mechanism ain't working anymore. Period.

Just remember: if you'll see something like this:
java.io.IOException: Server returned HTTP response code: 407 for URL: http://cobertura.sourceforge.net/xml/coverage-04.dtd
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.setupCurrentEntity(XMLEntityManager.java:677)
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.startEntity(XMLEntityManager.java:1315)
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.startDTDEntity(XMLEntityManager.java:1282)
at com.sun.org.apache.xerces.internal.impl.XMLDTDScannerImpl.setInputSource(XMLDTDScannerImpl.java:283)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$DTDDriver.dispatch(XMLDocumentScannerImpl.java:1194)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$DTDDriver.next(XMLDocumentScannerImpl.java:1090)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:1003)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:140)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:511)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:808)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205)
at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
at _Events.replaceClosureNamesInXmlReports(_Events.groovy:118)
at _Events$replaceClosureNamesInXmlReports.callCurrent(Unknown Source)
at _Events.replaceClosureNamesInReports(_Events.groovy:89)
at _Events$_run_closure2.doCall(_Events.groovy:42)
at _GrailsEvents_groovy$_run_closure5.doCall(_GrailsEvents_groovy:58)
at _GrailsEvents_groovy$_run_closure5.call(_GrailsEvents_groovy)
at _GrailsTest_groovy$_run_closure1.doCall(_GrailsTest_groovy:203)
at TestApp$_run_closure1.doCall(TestApp.groovy:82)
at gant.Gant$_dispatch_closure5.doCall(Gant.groovy:381)
at gant.Gant$_dispatch_closure7.doCall(Gant.groovy:415)
at gant.Gant$_dispatch_closure7.doCall(Gant.groovy)
at gant.Gant.withBuildListeners(Gant.groovy:427)
at gant.Gant.this$2$withBuildListeners(Gant.groovy)
at gant.Gant$this$2$withBuildListeners.callCurrent(Unknown Source)
at gant.Gant.dispatch(Gant.groovy:415)
at gant.Gant.this$2$dispatch(Gant.groovy)
at gant.Gant.invokeMethod(Gant.groovy)
at gant.Gant.executeTargets(Gant.groovy:590)
at gant.Gant.executeTargets(Gant.groovy:589)

you're having issues with authorization (it's the 407 part of this call stack)

I hope this will help save someone tons of time that I spent to figure this damn thing out.

Oh! And if it'd not be enough it works just fine on Windows when you're logged in to the domain. Go figure!

Saturday, December 18, 2010

Grails T'n'T: Accessing current controller from a command object

Hi there folks!

This time we're going to talk about how to access the current controller instance from anywhere in the code. We're going to demonstrate this by the Command object example.

Imagine you're in a command object's method and want to call the render method. All would be nice and dandy if it'd be the controller itself but it turns out the command object is more like a domain class (with its ability to verify field values and so on) than anything else. But... there's hope!

Let's add the following method to our command object:
private getController() {
RequestContextHolder.
requestAttributes.
request.
getAttribute(GrailsApplicationAttributes.CONTROLLER)
}

This way we get a read-only property called controller that we can use to call the render method.

But there's more!

Imagine you'd like to access the current request, response or session from the command object. All you need to do is to get there via the controller:
controller.session
controller.request
controller.response

Even the params element of the controller is available!

I sure hope this will help you out in refactoring your code from the controller into external classes like the command objects.

Have fun!

Grails and external configuration - the easy way

Hi folks!

This time we're going to work towards the ability to change application's configuration after deployment. In spring what you usually do is allow for loading some settings from a configuration file first prior to setting the defaults. This way once a particular key has been set in the override it's not going to be overridden by the defaults in your applicationContext.xml or beans.xml (however you wanna call it).

In Grails thanks to the existence of another mechanism we can do it differently. We can instruct Grails to load overrides if they have been declared in either the system properties for currently running process (using the -D notation in JAVA_OPTS) or plain in environment options.

The first option is dead simple. What you need to do is to go to your conf/Config.groovy and uncomment the following lines near the top of the file (at least in the original one):
if(System.properties["${appName}.config.location"]) {
grails.config.locations << "file:" + System.properties["${appName}.config.location"]
}

Unfortunately when you do that and set the proper setting during the invocation of java process that started your application (that'd be Tomcat) you'll be presented with an error message like this:
log4j:ERROR Error initializing log4j: No signature of method: 
groovy.util.ConfigObject.leftShift() is applicable for argument
types: (java.lang.String) values: [file:]
Possible solutions: leftShift(java.util.Map$Entry), leftShift(java.util.Map)
groovy.lang.MissingMethodException: No signature of method:
groovy.util.ConfigObject.leftShift() is applicable for argument types:
(java.lang.String) values: [file:]
Possible solutions: leftShift(java.util.Map$Entry), leftShift(java.util.Map)
at Config.run(Config.groovy:17)
2010-12-18 22:30:46 org.apache.catalina.core.StandardContext start
SEVERE: Error listenerStart
2010-12-18 22:30:46 org.apache.catalina.core.StandardContext start
SEVERE: Context [/] startup failed due to previous errors

This is due to the fact that the grails.config.locations element is not set by default. To fix this simply add the following line just before the the code you've just uncommented:

grails.config.locations = []

Once that's done you're able to specify the additional config location in JAVA_OPTS and live is good :)

The other option is to change the predefined code to look for an environment variable instead:

if(System.getenv()["${appName}.config.location"]) {
grails.config.locations << "file:" + System.getenv()["${appName}.config.location"]
}

This way instead of looking for parameters specified via the -D option while invoking the Java virtual machine it'll look for an environment variable.

Surely you'll find more ways to specify the config file location. The beauty of this solution lies in diversity :)

I hope it'll help someone!