Don't use those libraries - instead use the good old grails-xfire plugin. This guy just works out of the box with .NET 3.5 and 4.0. In C# just add a web reference and you're all set!
More on this topic soon - stay tuned!
web.config
getting this guy to work was just a matter of minutes. 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.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.dataSource
as follows:dataSource {
logSql = false // disable SQL statements logging
}
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"
}
...
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 :)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...)
}
.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.conf/Config.groovy
file:grails.sitemesh.default.layout = "none"
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 :)application.gsp
looks just wrong all along.
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 :)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 :)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.<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')}";
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.<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.name
parameter comes in handy<g:script name="common" />
This way the common
script will be requested.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)
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!private getController() {
RequestContextHolder.
requestAttributes.
request.
getAttribute(GrailsApplicationAttributes.CONTROLLER)
}
controller
that we can use to call the render
method. controller.session
controller.request
controller.response
params
element of the controller is available!if(System.properties["${appName}.config.location"]) {
grails.config.locations << "file:" + System.properties["${appName}.config.location"]
}
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
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 = []
if(System.getenv()["${appName}.config.location"]) {
grails.config.locations << "file:" + System.getenv()["${appName}.config.location"]
}