Grails BuildConfig.groovy, difference between build, compile, and runtime? - grails

What's the difference between build, runtime, and compile, in BuildConfig.groovy (1.3.7)
grails.project.dependency.resolution = {
plugins {
build "acme:acme-cache:latest.integration"
}
dependencies {
build "com.foo.bar:foobar:1.0.5"
runtime "org.apache.httpcomponents:httpclient:4.0.3"
compile("com.thoughtworks.xstream:xstream:1.3.1")
}
}

build - dependency that is only needed by the build process
runtime - dependency that is needed to run the application, but not compile it e.g. JDBC implementation for specific database vendor. This would not typically be needed at compile-time because code depends only the JDBC API, rather than a specific implementation thereof
compile - dependency that is needed at both compile-time and runtime. This is the most common case
There are a couple of other dependency scopes:
test - dependency that is only needed by the tests, e.g. a mocking/testing library
provided - dependency that is needed at compile-time but should not be packaged with the app (usually because it is provided by the container). An example is the Servlet API

It seems the 2 previous answers conflict on the distinction between compile and build. I believe that build is the scope that includes grails compile and grails run-app, while compile is just the former.

Starting from Grails 3, dependencies are managed by Gradle. The grails-app/conf/BuildConfig.groovy file has been replaced by the build.gradle file in the project's root.
The Grails user guide explain how to set grails depencies with gradle. See also the related Gradle documentation for further details on managing dependencies using it.

A couple grails commands help illustrate the difference. Consider grails run-app and grails compile. grails compile is the compile step and will include compile-time dependencies. grails run-app is the run step and will include runtime dependencies. Build dependencies are anything that you might need to run any of these commands, for example, a custom script that hooks into some build events.
So you would pick the one that best fits when you need to be certain the dependency is included.

Related

java.lang.ClassNotFoundException:org.yaml.snakeyaml.Yaml

I am using Grails 2.3.8
I am using - org.yaml.snakeyaml.Yaml class.
Didn't have any issues with GGTS workspace finding the package during auto
complete in the source.
But when running the application I get
java.lang.ClassNotFoundException:org.yaml.snakeyaml.Yaml
My assumption was this is part of the core Grails and the jars will be
included automatically.
Do I have to configure and add the jar or dependency in the
BuildConfig.groovy ?
Grails 3 uses Yaml and includes it as a dependency but prior to 3.0 it didn't, so you need to configure it like any third-party dependency in BuildConfig.groovy, e.g.
dependencies {
...
compile 'org.yaml:snakeyaml:1.14'
}

Recommended scope for grails plugins

I've got a list of grails plugings in my 1.3.7 app.
I'm converting it to 2.1.0 and doing a cleanup.
In my application.properties I have the following:
plugins.build-test-data=2.0.3
plugins.fixtures=1.1
plugins.hibernate=2.1.0
plugins.pretty-time=0.3
plugins.mail=1.0
plugins.quartz=0.4.2
plugins.spring-security-core=1.2.7.3
plugins.tomcat=2.1.0
I'm moving them all to my BuildConfig.groovy instead.
I'm curious as to what is the most appropriate scope for each plugin?
Thanks
My usual rule of thumb is
build scope for plugins that are part of the build process but shouldn't go into the WAR for production deployment
test scope for things that should be available to tests but not to application code
runtime scope for plugins (or JAR dependencies) that you need for the app to run but which you don't want to tightly couple your app to (you can't import a class from a runtime dependency into one of your app's own classes, for example)
compile scope for everything else
If in doubt, compile will definitely work, as plugins in application.properties are treated as if they were declared in compile scope.
So tomcat definitely wants build scope, spring-security-core definitely wants compile, I guess fixtures and build-test-data should be test, the others compile or runtime depending on whether you need to import any of their classes directly.

Grails wants to downgrade my plugins when I copy my app to a new machine

When I copy my app to a different machine and do 'grails run-app' grails seems to skip a step as far as updating its local plugins. (What I mean is the first computer has just done Downloading: plugins-list.xml, but when I run the app on the second machine, the new machine will not do that step.) I get this message:
Loading Grails 2.0.3
Configuring classpath
Environment set to development.....
Packaging Grails application
You currently already have a version of the plugin installed [resources-1.1.6]. Do you want to update to [resources-1.1.5]? [y,n] n
Plugin resources-1.1.5 install aborted
Compiling 92 source files
Am I diagnosing this correctly, and how do I force an update? Also, if I do accept the downgrade my app breaks. Not sure whats up with that as it was working with 1.1.5 for a while..
What I feel like is happening is that grails makes a note in the project when grails' plugin magic was last updated, so that when I move the project the other grails mistakenly thinks it just updated. Is this at all correct?
Are you specifying your plugins in your BuildConfig.groovy file or are you "installing" the plugins using the install-plugin command? My reading indicates usage of the install-plugin command isn't recommended anymore, you should instead specify the plugin as in your BuildConfig.groovy file then Grails will just handle it regardless of what machine you deploy on.
Example:
plugins {
/*
* build - dependency that is only needed by the build process
* compile - dependency that is needed at both compile-time and runtime. This is the most common case
* provided - dependency that is needed at compile-time but should not be packaged with the app (usually because it is provided by the container). An example is the Servlet API
* runtime - dependency that is needed to run the application, but not compile it e.g. JDBC implementation for specific database vendor. This would not typically be needed at compile-time because code depends only the JDBC API, rather than a specific implementation thereof
* test - dependency that is only needed by the tests
*/
runtime ":cached-resources:1.0"
runtime ":database-migration:1.1"
runtime ":hibernate:$grailsVersion"
runtime ":jquery:1.7.1"
runtime ":resources:1.1.6"
runtime ":yui-minify-resources:0.1.4"
runtime ":zipped-resources:1.0"
compile ":cache-headers:1.1.5"
compile ":commentable:0.8.1"
compile ":jquery-ui:1.8.15"
compile ":joda-time:1.4"
compile ":searchable:0.6.3"
compile ":spring-security-ldap:1.0.6" // Also installs spring-security-core
build ":tomcat:$grailsVersion"
}
Note too that some plugins also require a special entry in the dependencies section of your BuildConfig.groovy file. The JodaTime plugin is one such plugin.
dependencies {
compile "org.jadira.usertype:usertype.jodatime:1.9"
}
A plugin's docs should specify if any entry in the dependencies section is needed.

Does Grails + Maven + JCL work in conjunction?

I'm working with IntelliJ IDEA 10.0.1 and Grails 1.3.7. I have a mavenized Grails project which depends on many logging libraries.
Here's the problem:
I have to use JCL as logging framework, but grails per default is working with SLF4J and has some default dependencies like jcl-over-slf4j, which are inherited by every grails project. First of all I have excluded every jcl-over-slf4j transitive dependency in my project pom file and verified with mvn dependency:tree that my pom is clean of any SLF4J bridging libraries.
But nevertheless jcl-over-slf4j is still beeing downloaded to my local maven repo when I try to start my grails app. This leads obviously to a StackOverflowError at runtime, since both jcl-over-slf4j and slf4j-jcl are in the classpath.
So because of which declaration the jcl-over-slf4j dependency is still beeing downloaded?
Since my pom is clean the obvious conclusion would be that Grails itself depends on those libraries. As mentioned before Grails has some default dependencies, on which every Grails project depends.
I know that I can exclude inherited depencencies in the BuildConfig.groovy file and if I run grails dependency-report I can also see that these dependencies are not listed anymore.
grails.project.dependency.resolution = {
inherits("global") {
excludes "jcl-over-slf4j", "jul-to-slf4j", "slf4j-log4j12"
}
}
But even then the jcl-over-slf4j dependency is still beeing downloaded to my repo when I start my grails app! Am I missing something? Is there a different way to exclude inherited grails dependencies when you're using a mavenized grails project?
Any help would be appreciated
Thanks!
Slash
Ok I think I got the answer now..
The problem is that the defined maven-grails-plugin (which is mandatory when you use maven + grails) within my pom file depends on jcl-over-slf4j and therefore gets downloaded when I start my application through maven. With my current maven version (2.2.1) it's not possible to exclude a dependency from a plugin. There is also a jjira issue regarding this problem. Can not exclude a dependency from a plugin
As soon as I remove the maven-grails-plugin the dependency is not downloaded anymore, but as drawback I'm not able to start the application through maven anymore..
Lessons learned: Don't use Maven + Grails + JCL in conjunction.
Note that with mvn dependency:tree just project dependencies are listed, but plugin dependencies are NOT listed.
Hope this is of any help!
Regards Slash

Grails Dependency Resolution

I'm a bit of a Grails newbie. I have an app which works fine in Eclipse but when I deploy in production falls over because of missing dependencies.
When I run the dependency report it shows all the dependencies are automatically present for 'build' but absent for 'runtime'.
What's the neatest way to migrate the dependencies from to runtime so (I hope) they get copied into my war file?
Also, I'm using the sanitizer plugin. This runs fine in development but has the dependencies missing from 'runtime' so falls over. If I manually add, for example, one of the dependencies into BuildConfig.groovy ("org.owasp.antisamy:antisamy:1.4.3") then grails falls over with this error:
loader constraint violation: loader (instance of ) previously initiated loading for a different type with name "org/xml/sax/SAXParseException"
I'm assuming that this is a classpath issue but I'm not sure why this only happens when I manually add the dependency - surely it's present all the time?
You're right, you have to add missing runtime dependencies to BuildConfig.groovy. The simplest thing would be to copy them from the plugin's BuildConfig.groovy to your app's one. You should also raise a JIRA for the respective grails plugin to get this fixed upstream.
Lots of jars out there in the Maven repositories have their dependencies not correctly defined in their pom file.
There is a way to fix that in BuildConfig.groovy, by switching off transitivity:
runtime('org.owasp.antisamy:antisamy:1.4.3') {
transitive = false
}
Instead of 'transitive=false' you might also experiment with excluding only specific dependencies using e.g.
excludes "xml-apis", "xerces"
inside the 'runtime' closure.

Resources