Excluding grails-plugin dependencies using the POM - grails

Gents, ladies...
Here is the issue :
I am integrating a grails application within a complex and heterogeneous system that uses maven to build and fetch dependencies.
Fair enough, there are a few different ways to add a plugin, but I would like to have all the dependencies managed by maven, as the conflicts and scopes in the dependency trees would then be solved by maven.
This will install the hibernate plugin at validation time, and resolve its dependencies
<execution>
<id>Hibernate plugin</id>
<phase>validate</phase>
<goals>
<goal>install-plugin</goal>
</goals>
<configuration>
<pluginName>hibernate</pluginName>
<pluginVersion>${grails.version}</pluginVersion>
</configuration>
</execution>
Apparently, there is no way to specify exclusions directly in the execution configuration to prevent it from resolving its dependencies (in the dependencies.groovy script) independently.
I tried
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.11.0.GA</version>
<scope>provided</scope>
</dependency>
The dependency will not appear in the lib dir of the WEB-INF folder in the target build dir. However it is still packaged in the war archive.
Remember the aim is to use maven for all things relating to dependencies.
But anyway since it seems there is no hope of excluding it using the pom, I try using the BuildConfig with :
case Environment.PRODUCTION :
build( "org.grails.plugins:hibernate:1.3.7" ) {
excludes "javassist"
}
break
This was a last resort, and it works. Specifying the build here, will effectively override the dependencies that come from the groovy script.
So my question is, is there anyway to override these dependencies using maven ?
Obviously I verified that the dependency I was trying to scope in provided isn't included anywhere else (it is excluded from grails-gorm).
Is there an easy way to solve this ?
UPDATE :
To prevent the war from resolving jar dependencies, there is a --nojars flag, but the war goal of the grails war mojo doesn't allow the passing of args. The exec mojo does, however there is only one execution spec possible for an instance of this plugin, and no lifecycle phase can be specified for the exec mojo.

I think you were on the right track in your first attempt to mark the dependency as provided. The part that you missed is probably that you did not disable the grails dependency management. You do that by setting pom true in BuildConfig.groovy and remove all other dependencies, like this:
grails.project.dependency.resolution = {
pom true
// inherit Grails' default dependencies
inherits("global") {
}
}
Once this is done, maven will handle all depencencies.
EDIT: I just realized that this was a really old post so pom true may not have been introduced in the Grails version you were using then. I think it came in 2.2 or something like that.

Related

How Jenkins plugins works

I had a situation where I have developed my own Jenkins plugin for the first time. The main purpose of the plugin is to publish a message to Google Cloud Platform. All the code that I have written in Jenkins is working fine in the local environment from eclipse. But when I am using the same code in Jenkins it is causing some dependency errors. Any help is really appreciated.
Thank you.
Note: Jenkins and Eclipse are on the same machine
How Jenkins resolves its dependencies is really a concern here for me.
Eclipse uses the M2eclipse plugin to add your dependencies to the classpath when running your plugin from Eclipse.
Jenkins only resolves dependencies between plugins. Furthermore Jenkins expects the .hpi packages to be self-contained, i.e. containing all JAR dependencies you need. mvn package should copy the jars of all your dependencies and put them in the .hpi file in the WEB-INF/lib folder.
In your specific case it seems that the Google Cloud implementation expects some implementation of a channel service provider on the classpath, so you should add a dependency on grpc-okhttp or grpc-netty, so they get packaged into the .hpi file as well.
Sometimes there could be a choice of class loader issue so please add follwing lines of code before calling classes of Google.
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
Also add the following code in Jenkins plugin pom.xml to specify Jenkins that the dependencies in the pom.xml should be loaded first rather than Jenkins dependencies.
<pluginManagement>
<plugins>
<plugin>
<groupId>org.jenkins-ci.tools</groupId>
<artifactId>maven-hpi-plugin</artifactId>
**<configuration>
<pluginFirstClassLoader>true</pluginFirstClassLoader>
</configuration>**
</plugin>
</plugins>
</pluginManagement>

When and how does gradle resolve its dependencies?

I'm trying to re-write our build to Gradle, but we want to keep the dependency management in Ivy, for internal reasons.
So while trying to do that, I'm having several questions regarding the way gradle handles its dependencies:
When does gradle resolve dependencies (without Ivy or anything)?
When adding IvySettings and ivy.xml, do I need to call something similar to ant's ivy:resolve or ivy:configure, or does Gradle take care of that? If so, when and how?
Gradle resolves dependencies (more precisely configurations) on first use (typically by a task). Gradle doesn't read ivysettings or ivy.xml. (It does read ivy.xml files in the repository.) All information about dependency resolution is configured in Gradle build script(s).
In regards to (2), I managed to get gradle to read an ivy.xml file, and resolve the dependencies from there.
Gradle doesn't take care of that naturally, but using code from this issue, with a few tweaks, managed to get dependencies with gradle.
further more, there is a IvyXML plugin for gradle, with claims it can take care of most of this stuff.

Using profiles in multimodule project

I have a multimodule maven project. Project layout is described below:
PARENT
|-CHILD1
|-CHILD2
Parent project has pom packaging type and declares CHILD1 and CHILD2 projects as modules. Also PARENT project declares profile dev which declares some property.
CHILD1 project has jar packaging type and "overrides" PARENT dev profile by adding some dependency(dependency on commons-collections for example).
CHILD2 project has war packaging type and has dependency on CHILD1 project. Also CHILD2 "overrides" parent dev profile by adding another dependency(dependency on commons-io for example, I mean dependency that is not related with that one in project CHILD1).
Then when I run mvn clean install -Pdev maven doesn't put commons-collections.jar(dependency that is declared in CHILD1 project) to WEB-INF/lib of CHILD2 project, but commons-io.jar is there.
So, the question is: Why does not maven put dependencies from profiles that are declared in dependent projects of target project if target project declares another set of dependencies in that profile?
Actually I have much more projects and much more dependencies that varies in different profiles. And I want to declare project specific dependencies in that project pom.xml(supposing that declaring profile in project will "override" parent profile declaration)
I am assuming that you want to be able to test locally when developing, test your changes against a staging environment and finally deploy to production.
The critical thing that you need to keep in mind is that when an artifact gets deployed to the local/remote repository, the active profiles is not part of what gets deployed, so when you add dependencies via profiles things become very dangerous as you have no way of knowing if the webapp was built with the DEV profile active or the PROD profile active, and then when that built artifact gets deployed into production you could be royally screwed over.
So the short of this is that you ensure that your artifacts are independent of deployment environment.
This means that, for example, you will pick up configuration from:
files on the classpath
system properties
jndi entries
So for example, if deploying to Tomcat, you might put a configuration.properties into $CATALINA_HOME/lib
Your webapp on startup will use getClass().getResource('/configuration.properties') to resolve the properties file and fail to start-up if the file is missing (fail-fast)
you can let your unit/integration tests use a different config by putting a test version of configuration.properties in src/test/resources.
You use the same principle for the <scope>provided</scope> style dependencies of your application. In otherwords a dependency that the container is contracted with providing should be provided by the container. So you might build the production version of tomcat/jetty for yourself using Maven also and add in the required dependencies into that assembly. This would be things like the production version uses a MySQL database, so you need to add the mysql-jdbc driver into to $CATALINA_HOME/lib. It is relatively easy to do this with the assembly plugin as you are really just repacking a zip with some bits included and others excluded.
When testing locally you will want to make use of the helper plugins' run goals such as jetty:run and tomcat:run. The solution here is that there is nothing wrong with giving these plugins dependencies via profiles because you are not affecting the dependencies of the artifact you are only affecting the plugin's classpath.
e.g.
<project>
<!-- ... some stuff .. -->
<profiles>
<profile>
<id>DEV</id>
<build>
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<dependencies>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.18</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
You can also configure system properties or classpath additions to pull in the required configuration file.
The net result of all this is that the artifact remains environment independent and you can test easily against the various environments
Hope this answers your question (even if sideways)

How to skip building of the pom in multi-module project

I'm trying to optimize my build process (in development) in term of time to build the whole tree of maven multi-module project. Some of the POM are actually aggregation of sources/libraries that rarelly (and typically) never change. So specific sub-questions are
Is it possible to somehow configure maven to not build pom if there are no changes in sources specified in POM:project/build/sourceDirectory attribute?
Or is it possible to (at least) conditionally disable maven-bundle-plugin? - it takes most of the time.
Google could not find anything relevant Q#1. Typical solution does not work for #2 - when i try to specify 'executions' for maven-bundle-plugin (like this)
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>${maven-bundle-plugin.version}</version>
<extensions>true</extensions>
<executions>
<execution>
<id>osgi-bundle</id>
<phase>bundle</phase>
<goals>
<goal>bundle</goal>
</goals>
i receive this error in output
[bundle:bundle]
Bundle artifact-id:bundle-id:bundle:0.1.0-SNAPSHOT : The JAR is empty: dot
Error(s) found in bundle configuration
Any help is appreciated. I'm aware about following:
* Disable a Maven plugin defined in a parent POM
(maven-bundle-plugin can't work with 'executions' tag)
* Skip execution of a maven plugin if a file does not exist (maven-bundle-plugin does not have skip confiuration option)
* How to skip lifecycle phase in multi maven module (the same as previous)
* If entire maven-bundle-plugin is moved into profile, maven does not recognize packaging=bundle.
Finally I have to admit that (C) Eugene Kuleshov - "Maven generally don't track sources/changes, so it is always a full build."
But, returning back to Java after 5+ on .NET and 5+ years erlier on C++, it looks weird for me that such a common feature like incremental build is not support by widely used tool having a history of 10+ years. So I could not spend my time on waiting to rebuild each and every unchanged module in my multi-module project and decided to make customized version of Maven 3.0.4 :)
Feel free to grab it here http://code.google.com/p/maven-onchange-activator/, try and report issues.
Maven generally don't track sources/changes, so it is always a full build. However to disable any plugin you could move it into profile and then enable/disable the whole profile, e.g. either conditionally or from the command line.
You should check things like
mvn -am
in relationship with
mvn -pl ...
so doing a build like:
mvn -am -pl SubModule clean package
will build only those modules which have been changed and which needed to be built as a result of a dependency to the change module.
I would suggest switching to Gradle.
Gradle has such support out of the box (no configuration needed) and conversion from Maven should be easy.

Grails Plugin Maven Integration

I'm trying to create Mavenized Grails application. Everything works fine but as I understood all the dependencies (all .jars like mysql-connector and also all grails (public) plugins like spring-security-core plugin) should be listed in pom.xml.
The thing is that I don't know how to include public grails plugins (is there any Maven repository for that, or should I include used plugins into my local repo?). Or is the proper way how to handle grails plugin to list them in "application.properties" and let the grails to manage these plugins?
Thank you for any comment.:-)
Mateo
You can specify your plugin dependencies in grails-app/conf/BuildConfig.groovy, for example:
grails.project.dependency.resolution = {
plugins {
runtime ':hibernate:1.2.1'
}
}
Update
In response to your comments below, a plugin dependency specified in BuildConfig.groovy (or application.properties) will still be resolved by Grails rather than Maven. I don't think there's any way that you can get Maven to resolve a Grails plugin dependency, because Maven can only work with JAR dependencies in Maven repositories. Remember, Grails plugins are not (typically) available from Maven repositories.
If you want to hand as much control as possible over to Maven, you can try excluding the JARs from your plugin dependencies, e.g.
plugins {
runtime( "org.grails.plugins:hibernate:1.2.1" ) {
excludes "javassist"
}
}
and add them to your pom.xml instead. Here be dragons (see below).
Editorializing
FWIW, unless you really have to build your Grails project with Maven (e.g. because another Maven project depends on it), my advice would be don't. I say this because Maven is very much a second-class citizen in the world of Grails build tools. The usual way to build a Grails app is using the built-in GAnt commands. Future versions of Grails will move towards Gradle as the default build tool, so it seems that Maven will be an afterthought for the forseeable future
By default, Grails plugins are included at the source level. A plugin zip is expanded, and the plugin source is compiled as part of the grails build process.
Since 2.0, grails can use binary plugins. You can depend on plain old JARS if those jars represent binary grails plugins.
Binary grails plugins can be referenced by normal maven coordinates.
Your project's BuildConfig.groovy is where you specify maven repositories and binary plugins.

Resources