Why doesn't groovy use classpath argument? - groovy

Invoking a groovy script using CLASSPATH prefix as follows works fine:
CLASSPATH=/path/to/classes groovy -e "(new stuff.XMLUtils()).printIt('test string')"
but changing it to use the classpath arg doesn't:
groovy -classpath /path/to/classes -e "(new stuff.XMLUtils()).printIt('test string')"
and gives the error:
script_from_command_line: 1: unable to resolve class stuff.XMLUtils
Can anyone explain why this is? (The stuff.XMLUtils is just some groovy script i've compiled into /path/to/classes
)
I've done some investigation, and using the following groovy script to dump the classloader
def printClassPath(classLoader) {
println "$classLoader"
classLoader.getURLs().each {url->
println "- ${url.toString()}"
}
if (classLoader.parent) {
printClassPath(classLoader.parent)
}
}
printClassPath this.class.classLoader
With the -classpath arg, i see no entry in the classloader for the passed in classpath arg, (in fact, the only directory is the current working dir), e.g.:
groovy.lang.GroovyClassLoader$InnerLoader#4911b910
groovy.lang.GroovyClassLoader#18203c31
sun.misc.Launcher$AppClassLoader#35a16869
- file:/usr/share/java/ant.jar
- ... (removed for brevity)
- file:/home/admin/groovy/
sun.misc.Launcher$ExtClassLoader#77cde100
- file:/usr/java/jdk1.6.0_23/jre/lib/ext/sunjce_provider.jar
- ...
Using the CLASSPATH=... version shows that the PWD entry above is replaced by the value i've set in the variable.
And if I add debug to the groovy shell executable, the difference in the java call is that the -classpath arg version adds no entry to java's classpath entry (which is ultimately why it's giving a class not found error), but the CLASSPATH=... version does add the path.
Is this a bug in groovy?
EDIT: simple failing example
- - - - xu.groovy
package stuff
def printIt(string) { println string }
- - - -
groovyc -d classes xu.groovy
groovy -cp classes -e "(new stuff.xu()).printIt('test')" # fails
CLASSPATH=classes groovy -e "(new stuff.xu()).printIt('test')" # works
If I remove the package and references to stuff the failing example will work fine.

Answering this myself because I found a solution to the problem.
I was using the default groovy packages from yum in fedora, however found many issues (errors starting groovysh etc, unable to find jline package etc), and have wholly moved over to using downloaded versions from codehaus.org, and manually specifying GROOVY_HOME and editing path to invoke the downloaded one instead.
Now all my examples work as expected.

I'm on MSYS/Win32 + groovy 2.2 RC1 and have another twist:
groovy -cp "./*" script.groovy // Works!
but
groovy -cp some.jar script.groovy // ... not
For some reason, none of the above would work out in my case.

That's strange. I just tried to repeat your explained issue but everything seems to work fine (I made tests with Groovy-Version 1.8.6, 1.7.7 and 1.7.0 on my Ubuntu Computer).
So which version do you use and what is your operating system?
In the Groovy Bug Tracker I have found the following bug: Command line option for classpath (--cp/--classpath) is broken on Windows. But this bug just affects old versions of Groovy (1.5.2, 1.5.3 and 1.5.4). So maybe an upgrade of Groovy will help to fix your problem...
PS: Normally I just would comment this, but unfortunately I haven't enough points for doing this :).

Related

Not able to execute groovy script from command ".GroovyRuntimeException: Conflicting module versions."

I have run groovy script for a while from command line. Recently I have started to work with spock/groovy in the eclipse. I have run couple of test using Groovy Console when console was loaded from eclipse. Any way after these activities I have tried to execute groovy from command line and it failed with the following error:
Caused by: groovy.lang.GroovyRuntimeException: Conflicting module versions. Module [groovy-xml is loaded in version 2.4.3 and you are trying to load version 2.4.1
I was using gvm tool to reinstall groovy and set is a primary version but still have the problem. Something was changed from eclipse where my groovy installation gets affected and can not be fixed by by reinstalling.
I have some search done but did not find solution. most solution were mentioning this problem but they were trying to fix this withing eclipse, where in my case I am trying to fix it outside of eclipse. Also will be nice if I be able to prevent this from happening in the future. If somebody have similar experience please share.
Thanks,
Alexander

Groovy scripts no longer work under Cygwin?

In older versions of Groovy, I could run Groovy as a shell script under Cygwin, following their own instructions for doing so:
$ cat ~/bin/hiworld
#!/usr/bin/env groovy
println("Hello world")
This worked. However, under (at least) Groovy 2.3.2 and 2.3.3, I'm seeing this instead:
$ hiworld
Caught: java.net.MalformedURLException: unknown protocol: c
java.net.MalformedURLException: unknown protocol: c
My best stab in the dark: "env" launches scripts via an absolute path (e.g. "groovy /home/myacct/bin/hiworld"), and newer versions of Groovy have been, un, 'improved' so that Groovy no longer understands how to handle this.
Indeed, I can produce the same error by doing that:
$ groovy ~/bin/hiworld
Caught: java.net.MalformedURLException: unknown protocol: c
java.net.MalformedURLException: unknown protocol: c
So I'm not sure how Groovy is (a) resolving that to a windows-style path, and then (b) failing to understand it's a windows-style path.
I can "fix" this, then, by running it thusly:
$ groovy $(cygpath -w ~/bin/hiworld)
Hello world
... but, c'mon, that's a completely insane way of having users launch a utility script. (Or I could write a "front" script, with just that line, to launch another script, of course. But then, for what I'm trying to ultimately accomplish, I might as well just give up on Groovy and distribute a runnable JAR with an associated launching script.)
So has Groovy simply dropped support for Cygwin? Or is it really possible that they've gone at least two releases without testing their own recommended way of running a script under one of the most popular environments?
If not, what am I missing or doing wrong?
Update: I thought it would be helpful to back up some of the things I'm suggesting here.
First, I want note Cygwin clearly is (or was) at least somewhat supported: groovyStart, for example, has considerable code in it supporting the Cygwin platform (seemingly as much as, say Mac OSX). As noted, it apparently worked fine under previous versions.
Currently, the last example resolves, under groovyStart, to this:
'/cygdrive/c/Program Files/Java/jdk1.7.0_51/bin/java' -classpath C:/cygwin64/home/myacct/opt/groovy-2.3.3/lib/groovy-2.3.3.jar -Dscript.name=/home/myacct/opt/groovy-2.3.3/bin/groovy -Dprogram.name=groovy -Dgroovy.starter.conf=C:/cygwin64/home/myacct/opt/groovy-2.3.3/conf/groovy-starter.conf -Dgroovy.home=C:/cygwin64/home/myacct/opt/groovy-2.3.3 '-Dtools.jar=C:/Program Files/Java/jdk1.7.0_51/lib/tools.jar' org.codehaus.groovy.tools.GroovyStarter --main groovy.ui.GroovyMain --conf C:/cygwin64/home/myacct/opt/groovy-2.3.3/conf/groovy-starter.conf --classpath . C:/cygwin64/home/myacct/bin/hiworld
Just to clarify, there's no problem invoking the JDK itself -- runs that part of the command runs just fine. The part which is broken is the very last argument: if I change
C:/cygwin64/home/myacct/bin/hiworld
to
file:///C:/cygwin64/home/myacct/bin/hiworld
... it works again. This agrees with my assertion above that "groovy" (the script) is indeed correctly converting from Cygwin/UNIX-style paths to a native Windows path, but the underlying process -- running in Windows Java -- is actually confused by having been a windows path! Apparently it was expecting a URL.
Update 2: Below, Warren makes the excellent suggestion of trying to use GVM. Sadly, this still produces the same error:
$ which groovy
/home/myacct/.gvm/groovy/current/bin/groovy
$ hiworld
Caught: java.net.MalformedURLException: unknown protocol: c
java.net.MalformedURLException: unknown protocol: c
$ sh $(which groovy) ~/bin/hiworld
Caught: java.net.MalformedURLException: unknown protocol: c
java.net.MalformedURLException: unknown protocol: c
Adding the "-x" flag to the previous command shows that Groovy is still using my Windows JVM (which isn't wrong, just noting) and is now referencing the GVM-installed libraries (shown here reformatted slightly for readability):
'/cygdrive/c/Program Files/Java/jdk1.7.0_51/bin/java' \
-classpath C:/cygwin64/home/myacct/.gvm/groovy/2.3.3/lib/groovy-2.3.3.jar \
-Dscript.name=/home/C400334/.gvm/groovy/current/bin/groovy \
-Dprogram.name=groovy \
-Dgroovy.starter.conf=C:/cygwin64/home/myacct/.gvm/groovy/2.3.3/conf/groovy-starter.conf \
-Dgroovy.home=C:/cygwin64/home/myacct/.gvm/groovy/2.3.3 \
'-Dtools.jar=C:/Program Files/Java/jdk1.7.0_51/lib/tools.jar' \
org.codehaus.groovy.tools.GroovyStarter \
--main groovy.ui.GroovyMain \
--conf C:/cygwin64/home/myacct/.gvm/groovy/2.3.3/conf/groovy-starter.conf \
--classpath . \
C:/cygwin64/home/myacct/bin/hiworld
As before, adding a "file:///" before the final argument seems to resolve the problem.
So I'm wondering perhaps if we're using a different version of the JVM or something?
Update 3: Upgrading to jdk1.7.0_60 (tried both 64- and 32-bit versions) but that didn't seem to make a difference. Java 6 exhibits the same problem, but also adds a complaint about missing NioGroovyMethods.
I'm not sure how Groovy is (a) resolving that to a windows-style path
The startGroovy script has specific code in it to detect Cygwin and use cygpath as necessary.
I discovered this by installing Groovy via GVM, the approved way of getting Groovy for Unixy platforms. (You do not want to use the native Windows distribution of Groovy in this case!)
The only tricky thing was figuring out how to set JAVA_HOME. Here, it needed to be:
$ export JAVA_HOME='/cygdrive/c/Program Files (x86)/Java/jre7'
If you're on a 64-bit version of Windows and have a 32-bit JRE installed as I do, this should also work for you. Otherwise, you may have to adjust the path.
Once I got gvm install groovy to succeed, your hiworld example worked fine here if I ran it as ./hiworld. This was with the 32-bit version of Cygwin with Java 1.7.0_55.
However, when I put it in the PATH and ran it as hiworld, as you are doing, this passed a fully-qualified path to the groovy wrapper script (e.g. /home/wyoung/bin/hiworld) instead of a relative path, which caused the startGroovy script to run the path through cygpath -m, which turns that into something like C:/cygwin64/home/wyoung/bin/hiworld. Oracle's JRE can't cope with forward slashes in local paths. It blindly assumes that forward slashes on Windows means it's a URL of some kind, so C: gets treated as the URL scheme, or "protocol" as they put it.
I don't know if this is a regression in Java or in the startGroovy script. Although you could pass a file:// URL here as you discovered, you can also pass a "proper" Windows path with backslashes instead of forward slashes. You get that from cygpath with the -w switch instead of -m. You have to be a lot more careful about avoiding accidental backslash escaping in this case, which may explain the regression.
Just hit the same problem and changed the exec call in the startGroovy script to the following (note the last two lines):
exec "$JAVACMD" $JAVA_OPTS \
-classpath "$STARTER_CLASSPATH" \
-Dscript.name="$SCRIPT_PATH" \
-Dprogram.name="$PROGNAME" \
-Dgroovy.starter.conf="$GROOVY_CONF" \
-Dgroovy.home="$GROOVY_HOME" \
-Dtools.jar="$TOOLS_JAR" \
$STARTER_MAIN_CLASS \
--main $CLASS \
--conf "$GROOVY_CONF" \
--classpath "$CP" \
"$(cygpath -w $1)" \
"${#:2}"
... that way the script being called is altered to a windows path with backslashes as suggested above, and then not interpreted as a URL it seems. Nasty hack, but at least I was able to execute my script again :)
Not sure if anyone still interests in this. But shortly I commented the above answer, I found a solution for this.
Update the "startGroovy" script with the following two changes:
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
ROOTDIRS="/c$SEP$ROOTDIRS" ## <<<< ADD THIS LINE;assuming cygwin on c: drv
and also replace the --mixed with --windows:
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
if [ $CHECK -ne 0 ] ; then
### change the --mixed to --windows here
patched=`cygpath --path --ignore --windows "$arg"`
else
patched="$arg"
fi
and it should work.

run Groovy CLI from groovy jar placed in war

I know about Groovysh, but I need to know if it is possible to run groovy CLI directly from groovy.jar placed in deployed war servlet (using one command). I can simplify question. Is there possibility to run Groovy CLI like it works, for example, in Clojure?
java -cp clojure-1.4.0.jar clojure.main
And CLI appears in terminal. This is how things look in clojure. I am looking for one line command which will run groovy CLI in terminal (using only groovy library to run it). I was looking for help in javadoc, found classes which should help, but don't know how to run it. :f
http://groovy.codehaus.org/api/groovy/lang/GroovyShell.html
(If someone knows solution which doesn't meet all criterias, also please answer.)
//EDIT
It seems that it needs groovy.jar, commons-cli.jar, antlr.jar, asm-util.jar and jline.jar. So I've added those files in my war file in WEB-INF/lib directory. Maybe it's good solution to make my own jar which role will be to call Groovy CLI from other jars, but now the question is, how ro run jar placed in WEB-INF/lib directory inside deployed war application via command line?
Greets
Seems like groovysh depends on more libs than the embeddable version contains. I managed to do what you want by using the following command:
$ java -classpath '*' org.codehaus.groovy.tools.shell.Main
But the current directory had to be the dir where all the groovy libs are; i.e. $GROOVY_HOME/lib:
$ cd $GROOVY_HOME/lib
$ java -classpath '*' org.codehaus.groovy.tools.shell.Main
Groovy Shell (2.0.6, JVM: 1.6.0_24)
Type 'help' or '\h' for help.
------------------------------------------------------------------------------
groovy:000>

How to run a Scala program via cron?

I wrote a small Scala application. I have 2 classes in one source file including the App trait runner to start the program. It works just fine when I run it in the terminal:
scalac update.scala // compiling
scala update // run it
Now I want to run it with a cron job. For this I edited sudo crontab -e and added this:
*/2 * * * * scala /usr/bin/local/update
and made the script executable but nothing happend so far. I'm not sure how to do it:
Do I have to make a jar file for this?
Do I have to add this before my classes or not?
#!/bin/sh
exec scala -savecompiled $0 $#
!#
Does anyone have some experience with this?
Thanks in advance.
I suspect scala isn't in $PATH where cron can see it.
Try the following in a shell session:
$ which scala
Which should output something like "/opt/scala/2.9.1/bin/scala" or something. Could be in /usr/local, any number of places - java and the unix filesystem don't really play together nicely.
So now you have two options:
Put the folder where scala lives in the system path (This will usually involve editing /etc/profile, but you don't specify the OS so I can't say for sure)
(Easier) Just change the the cron entry to call /full/path/to/scala rather than just "scala"
The scala command expects the name of a compiled runnable object or a file containing a scala script source (or a runnable jar file) as the thing to run.
If you have in update.scala object update extends App (and no package declaration) then after scalac update.scala (which should have produced a bunch of *.class files) scala update is the right thing to run.
If the produced class files are not in the current directory then the -classpath option should be used to tell scala where to find them, as in eg. scala -classpath /usr/bin/local update, if the class files are indeed in /usr/bin/local.
Saying scala /usr/bin/local/update would make sense if the file /usr/bin/local/update (this exact name) contained scala script source (that is more or less a sequence of scala expressions not wrapped in a class or object).

Groovy - Grab: why it continues to download the necessary jars ?

I have a script where a method is annotated with the #Grab annotation
#Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', version='0.5.2' )
everytime i run the script groovy downloads all the required jars from internet, this makes the execution of the script very slow.
Why is it doing this? It has just downloaded all the necessary jars, i see them in .groovy/grapes
Groovy 1.8.4 on Linux
Thanks for the help
I think it's an issue with the http-builder repo itself having dependencies with a version range.
A possible workaround is here
Also, http-builder seems to have a dependency on Groovy [1.5,1.7.99] so no idea what it does when you Grab using Groovy 1.8

Resources