How to get groovy grape script startup going faster - groovy

I've noticed there is like a 10 second hit using a groovy script with Grape annotations on my OSX box. Is it always this way? Can I make grape favor its cache (the depedencies are definitely already on the system in ~/.groovy/grapes...).

Some libraries (notably httpbuilder) use version ranges in their dependencies. There is a post here which describes how to increase the TTL for this version check in your grapeconfig.xml file.

Do you have a ~/.groovy/grapeConfig.xml file defined? The example given in the doco favours the local cache.
<ivysettings>
<settings defaultResolver="downloadGrapes"/>
<resolvers>
<chain name="downloadGrapes">
<filesystem name="cachedGrapes">
<ivy pattern="${user.home}/.groovy/grapes/[organisation]/[module]/ivy-[revision].xml"/>
<artifact pattern="${user.home}/.groovy/grapes/[organisation]/[module]/[type]s/[artifact]-[revision].[ext]"/>
</filesystem>
<!-- todo add 'endorsed groovy extensions' resolver here -->
<ibiblio name="codehaus" root="http://repository.codehaus.org/" m2compatible="true"/>
<ibiblio name="ibiblio" m2compatible="true"/>
<ibiblio name="java.net2" root="http://download.java.net/maven/2/" m2compatible="true"/>
</chain>
</resolvers>
</ivysettings>

Related

add http builder as a dependency of Groovy script

I'm trying to write a Groovy script that depends on the HTTPBuilder library. I'm trying to add this as a dependency of my script via the #Grab annotation shown below
#Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', version='0.7.1')
import groovyx.net.http.HTTPBuilder
// rest of script omitted
But when I run this script I get the error:
java.lang.RuntimeException: Error grabbing Grapes -- [download failed: commons-lang#commons-lang;2.4!commons-lang.jar]
I've tested using #Grab to add other dependencies to my script, and the same problem does not occur, why can't I add HTTPBuilder?
Grape may be configured to only look in your local Maven repo for dependencies. To instruct it to also check online repositories, create a config. file ~/.groovy/grapeConfig.xml and add something like the following to it
<ivysettings>
<settings defaultResolver="downloadGrapes"/>
<resolvers>
<chain name="downloadGrapes">
<filesystem name="cachedGrapes">
<ivy pattern="${user.home}/.groovy/grapes/[organisation]/[module]/ivy-[revision].xml"/>
<artifact pattern="${user.home}/.groovy/grapes/[organisation]/[module]/[type]s/[artifact]-[revision].[ext]"/>
</filesystem>
<!-- todo add 'endorsed groovy extensions' resolver here -->
<ibiblio name="codehaus" root="http://repository.codehaus.org/" m2compatible="true"/>
<ibiblio name="ibiblio" m2compatible="true"/>
<ibiblio name="java.net2" root="http://download.java.net/maven/2/" m2compatible="true"/>
</chain>
</resolvers>
</ivysettings>

Multi Projects with CCNET

I have GIT repo as below,
\main
\Module A
\Module B
\Shared
When i make a change on Module B, CCNET will make a build from Module A and then Module B,
I dont want CCNET to do this way.It will take a lot of time.
I just want ccnet build only changes on Module B.
Somebody please help me :
My 1 project in CCNET Config:
enter code here
<project name="Dashboard 5.0" queue="Dashboard_01" queuePriority="01" category="01">
<artifactDirectory>&pathToArtifactsDirectory;Dashboard 5.0\</artifactDirectory>
&workingDirectory;
<webURL>http://&buildServerAddress;/ccnet/server/&buildServerName;/project/Dashboard 5.0/ViewLatestBuildReport.aspx</webURL>
&modificationDelaySeconds;
<triggers>
<intervalTrigger seconds='30' buildCondition='IfModificationExists'/>
<scheduleTrigger time='03:00' buildCondition='ForceBuild' name='Scheduled'/>
<scheduleTrigger time='11:00' buildCondition='ForceBuild' name='Scheduled'/>
</triggers>
<state type="state" directory="&pathToStatesDirectory;Dashboard 5.0\" />
<sourcecontrol type="git">
<repository>&gitAddress;</repository>
<branch>master</branch>
<autoGetSource>true</autoGetSource>
<fetchSubmodules>false</fetchSubmodules>
<executable>C:\Program Files (x86)\Git\cmd\git.exe</executable>
<commitBuildModifications>false</commitBuildModifications>
<commitUntrackedFiles>false</commitUntrackedFiles>
<timeout>3000000</timeout>
</sourcecontrol>
<tasks>
<nant>
<executable>&pathToNantFile;</executable>
<baseDirectory>&pathToBuildScriptsDirectory;Dashboard 5.0\</baseDirectory>
<buildArgs>-D:projects_to_build=dashboard_framework</buildArgs>
<buildFile>cruise.build</buildFile>
<targetList>
<target>automate</target>
</targetList>
<buildTimeoutSeconds>3000</buildTimeoutSeconds>
</nant>
</tasks>
<publishers>
<merge>
<files>
<file>&pathDB5MainCheckoutDirectory;framework\build\test-reports\*Test.dll-results.xml</file>
<file>&pathDB5MainCheckoutDirectory;framework\build\test-reports\Test*.dll-results.xml</file>
<file>&pathDB5MainCheckoutDirectory;framework\build\test-reports\simian.xml</file>
</files>
</merge>
<xmllogger />
</publishers>
Any check in for Module A or Module B will cause the project node to start either way. What you are looking for is similar to what subversion update command on a sub folder does and Git is not intended to be this way. An alternative you can create a separate repository for each module. The build script or Nant task would have to be separated as well.
In Git, if you have several directories that are always checked out independently, then these are really two different projects and should live in two different repositories. You can merge them back together at a later point using Git Submodules

Doing a build when changes happen in either of two repositories AND a file system

I have a ccnet project which watches two SVN repositories for changes. Using a source control block of type multi worked fine for that. Now the project needs to watch the two repositories and a file. It needs to only build if one of the two repositories changed and the file changed.
I tried nesting a multi source control block in a multi source control block as follows(you may ignore all the variables):
<sourcecontrol type="multi">
<requireChangesFromAll>True</requireChangesFromAll>
<sourceControls>
<sourcecontrol type="multi">
<requireChangesFromAll>False</requireChangesFromAll>
<sourceControls>
<filtered>
<sourceControlProvider type="svn" autoGetSource="false">
<executable>$(svn-exe)</executable>
<timeout units="minutes">60</timeout>
<trunkUrl>$(svn-srcmwo)</trunkUrl>
<workingDirectory>$(mwo-localfull)</workingDirectory>
</sourceControlProvider>
<inclusionFilters>
<cb:mwo-include-filters/>
</inclusionFilters>
</filtered>
<filtered>
<sourceControlProvider type="svn" autoGetSource="false">
<executable>$(svn-exe)</executable>
<timeout units="minutes">10</timeout>
<trunkUrl>$(svn-orion)</trunkUrl>
<workingDirectory>$(orion-localfull)</workingDirectory>
<webUrlBuilder type="websvn">
<url>$(viewvc-orion){0}$(viewvc-config)</url>
</webUrlBuilder>
</sourceControlProvider>
<inclusionFilters>
<pathFilter>
<pattern>$(svn-orion-trunk)</pattern>
</pathFilter>
</inclusionFilters>
<exclusionFilters>
<pathFilter>
<pattern>$(svn-grsim-makfiles)</pattern>
</pathFilter>
</exclusionFilters>
</filtered>
</sourceControls>
</sourcecontrol>
<sourcecontrol type="filesystem">
<repositoryRoot>e:\build_listen</repositoryRoot>
</sourcecontrol>
</sourceControls>
</sourcecontrol>
but CCValidator gave the error:
Unused node detected: <sourcecontrol type="filesystem"><repositoryRoot>e:\build_listen&lt/repositoryRoot></sourcecontrol>
Does anyone see how this can be done - doing and AND on a file system and two repositories?
This nested source control thing is quite complicated indeed. First of all you missed the <sourceControls> tag in the outer multi sourcecontrol block. Secondly there is an important note in the CCNET documentation on multi sourcecontrol blocks:
Note that, due to the way the configuration gets parsed, if you are using a "multi" block, then the items within the element should not be elements (as you may expect). Instead, the name of the element should be the same as you would put in the "type" attribute when using a element.
That is just the way the source control blocks work in your existing configuration: <filtered> instead of <sourcecontrol type="filtered">.
So this should fix your problem:
<sourcecontrol type="multi">
<requireChangesFromAll>True</requireChangesFromAll>
<sourceControls>
<multi>
<requireChangesFromAll>False</requireChangesFromAll>
<sourceControls>
<filtered>
<sourceControlProvider type="svn" autoGetSource="false">
<executable>$(svn-exe)</executable>
<timeout units="minutes">60</timeout>
<trunkUrl>$(svn-srcmwo)</trunkUrl>
<workingDirectory>$(mwo-localfull)</workingDirectory>
</sourceControlProvider>
<inclusionFilters>
<cb:mwo-include-filters/>
</inclusionFilters>
</filtered>
<filtered>
<sourceControlProvider type="svn" autoGetSource="false">
<executable>$(svn-exe)</executable>
<timeout units="minutes">10</timeout>
<trunkUrl>$(svn-orion)</trunkUrl>
<workingDirectory>$(orion-localfull)</workingDirectory>
<webUrlBuilder type="websvn">
<url>$(viewvc-orion){0}$(viewvc-config)</url>
</webUrlBuilder>
</sourceControlProvider>
<inclusionFilters>
<pathFilter>
<pattern>$(svn-orion-trunk)</pattern>
</pathFilter>
</inclusionFilters>
<exclusionFilters>
<pathFilter>
<pattern>$(svn-grsim-makfiles)</pattern>
</pathFilter>
</exclusionFilters>
</filtered>
</sourceControls>
</multi>
<filesystem>
<repositoryRoot>e:\build_listen</repositoryRoot>
</filesystem>
</sourceControls>
</sourcecontrol>
I think you can't have two following sourcecontrol blocks.
You should refactor your projects as follow:
One project with only the filesystem trigger.
This will be the trigger for the next job
Another project linked to the previous one AND with your multi sourcecontrol triggers.
Have a look to CruiseServer Control Task to synchronize two jobs:

Make groovy script grab a jar off the filesystem like grape

Grape seems to work fairly well for adding jars to your classpath. It
also does a lot of other things such as fetching and dependency management.
e.g.
#!/home/robert/bin/groovy
import org.apache.commons.lang.StringUtils
#Grab(group='commons-lang', module='commons-lang', version='2.4')
def strings = ['Hello', 'Groovy', 'AVeryLongWord!', 'A simple sentence']
strings.each { String aString ->
println "$aString: ${StringUtils.abbreviate(aString,10)}"
}
Unfortunately if there is a jar on my filesystem that I want to
dynamically add to the filesystem then I have to resort to a much
uglier solution.
#!/home/robert/bin/groovy
def loader = this.class.classLoader.rootLoader
loader.addURL(new File("/home/robert/somejars/arithmetic-1.1.jar").toURI().toURL())
// can't use traditional package import
arithmeticMainClass = Class.forName("org.scharp.arithmetic.Main")
println "42 - 23 = " + arithmeticMainClass.subtract(42, 23)
// can't use "new" operator
myArithmeticObject = arithmeticMainClass.newInstance()
Is there a way to make grape grab a jar from the filesystem? If not,
can I somehow replicate what grape is doing in groovy/java?
I would like this solution to work for scripts that can be run by many users and many incompatible jars so adding jars to a common directory such as ~/.groovy/lib/ won't work.
I could create a local maven repository for local, jar libaries but
that seems like overkill.
This is how I solved this.
When Grape (Ivy) wants something it caches it under the ~/.groovy/grapes directory. All you need to do is just create your own ivy.xml file and throw your jar in there. I figured it out by just looking at some of the other artifacts donwloaded from maven. Here is a small example.....
We use Oracle here and I wanted it's jdbc jar file to be able to be 'Grabbed' by my Groovy scripts.
Unfortunately, I could not find any repository that had this jar on the web.
Step 1 : create directory ~/.groovy/grapes/com.oracle
Step 2 : create directory ~/.groovy/grapes/com.oracle/ojdbc6
Step 3 : create directory ~/.groovy/grapes/com.oracle/ojdbc6/jars
Step 4 : Get a copy of Oracle's ojdbc jar file and rename it. Our oracle version is 11.2.0.1.0 and we use Java6 so I got the locally installed ojdbc6.jar file and copied as ojdbc6-11.2.0.1.0.jar. This file I put into the directory created in the prior step.
Step 5 : create an ivy-11.2.0.1.0.xml config file.This file should be put into the directory created in step 2. For this step I heavily relied on examples from other artifacts grabbed. Any apache commons lib is a good example.
Here is my xml.
<?xml version="1.0" encoding="UTF-8"?>
<ivy-module version="2.0" xmlns:m="http://ant.apache.org/ivy/maven"
>
<info organisation="com.oracle" module="ojdbc6" revision="11.2.0.1.0" status="release" publication="20130102153401">
<license name="" />
<description homepage="">Oracle ojdbc driver</description>
</info>
<configurations>
<conf name="default" visibility="public" description="" extends="runtime,master" />
<conf name="master" visibility="public" description="" />
<conf name="compile" visibility="public" description="" />
<conf name="provided" visibility="public" description="" />
<conf name="runtime" visibility="public" description="" extends="compile" />
<conf name="test" visibility="public" description="" extends="runtime" />
<conf name="system" visibility="public" description="" />
<conf name="sources" visibility="public" description="" />
<conf name="javadoc" visibility="public" description="" />
<conf name="optional" visibility="public" description="" />
</configurations>
<publications>
<artifact name="ojdbc6" type="jar" ext="jar" conf="master" />
</publications>
</ivy-module>
Now I can use this jar in my groovy scripts with the following....
#Grapes([
#GrabConfig(systemClassLoader=true),
#Grab('com.oracle:ojdbc6:11.2.0.1.0'),
])
import groovy.sql.*
To make things easy for deploying this grape to multiple servers I created a zip file that I could extract anywhere....
$ unzip -qql oracle_jdbc_groovy_grape.zip
0 06-11-2012 13:50 .groovy/grapes/com.oracle/
0 06-12-2012 14:17 .groovy/grapes/com.oracle/ojdbc6/
0 06-12-2012 14:17 .groovy/grapes/com.oracle/ojdbc6/jars/
2111220 06-11-2012 11:46 .groovy/grapes/com.oracle/ojdbc6/jars/ojdbc6-11.2.0.1.0.jar
2349 06-11-2012 11:50 .groovy/grapes/com.oracle/ojdbc6/ivy-11.2.0.1.0.xml
You can customize the ivy settings that Grape uses by creating a ~/.groovy/grapeConfig.xml file.
Here's an example how to use the local file system as repository:
<ibiblio name="local" root="file:${user.home}/.m2/repository/" m2compatible="true"/>
There's been some interest in adding this feature to grape but nothing serious. My guess is that it's unlikely that this will be added in the near future. (6-18 months)
According to this enhancement, Grapes will now also search your local Maven repo, along with Maven Central.
You can install any jar(s) in your local repo by:
running mvn install in your project
using mvn dependecy:get; see documentation and example
using mvn install:install-file; see documentation and example

Disable automatic download for Groovy grapes

A sample script ss.groovy:
#Grab(group='org.codehaus.groovy.modules.http-builder',
module='http-builder',
version='0.5.0')
import groovyx.net.http.HTTPBuilder
println('done')
for some reason takes ~25 seconds to load when run with
groovy ss.groovy
and ~5 seconds when run with
groovy -Dgroovy.grape.autoDownload=false ss.groovy
as per this StackOverflow explanation. I tried doing manual initialization with
Grape.enableAutoDownload = false
Grape.grab(group:'org.codehaus.groovy.modules.http-builder',
module:'http-builder',
version:'0.5.0')
import groovyx.net.http.HTTPBuilder
println('done')
but this fails on import with:
/tmp/ss.groovy: 3: unable to resolve class groovyx.net.http.HTTPBuilder
# line 3, column 1.
import groovyx.net.http.HTTPBuilder
^
Is there a contained way to either:
Make it not download the artifacts automatically (preferred, as it allows for solving other issues, e.g. external site down while an artifact already exists in the local cache)
Make it startup faster in any other way
By contained I mean that all additional instructions should be either within script or, if no such one exists, an acceptable default (e.g. don't check the cached artifacts for updates - I would still, however, like to have automatic downloads globally) to be put in some of groovy config files (e.g. ~/.groovy/grapeConfig.xml or similar).
Update: The issue has been fixed, #GrabConfig(autoDownload=false) will be available in Groovy 2.2
Why not install a repository manager locally?
http://nexus.sonatype.org/
I use Nexus to proxy and cache all my 3rd party repositories. Groovy is the configured to retrieve from either it's local cache or Nexus:
<ivysettings>
<settings defaultResolver="downloadGrapes"/>
<resolvers>
<chain name="downloadGrapes">
<filesystem name="cachedGrapes">
<ivy pattern="${user.home}/.groovy/grapes/[organisation]/[module]/ivy-[revision].xml"/>
<artifact pattern="${user.home}/.groovy/grapes/[organisation]/[module]/[type]s/[artifact]-[revision].[ext]"/>
</filesystem>
<!-- Local Nexus Repository -->
<ibiblio name="nexus" root="http://localhost:8081/nexus/repositories/public" m2compatible="true"/>
</chain>
</resolvers>
</ivysettings>
This doesn't seem to be possible with the current (Groovy 1.8.1) implementation. I created an improvement ticket: http://jira.codehaus.org/browse/GROOVY-4943.

Resources