I want to slowly migrate to a better build and dependency resolution process, we are currently using Ant with local file dependencies.
We chose to migrate to gradle ,so as a first step I would like to simply run my current ant build from a gradle sript. But i dont know how to pass the -lib classpath to ant. Im getting errors of missing dependencies.
This is my gradle.build:
apply plugin: 'java'
task someProperties {
ext.LIBS_CATW = "backend/java-src/lib"
ext.LIB_SERVLET = "/usr/local/apache-tomcat-7.0.32/lib/servlet-api.jar"
}
dependencies {
compile files('/usr/local/apache-tomcat-7.0.32/lib/servlet-api.jar')
compile fileTree(dir: 'backend/java-src/lib', include: '*.jar')
}
I use this shell script to run ant from command line.
#!/bin/bash
export JAVA_HOME="/System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home"
ROOT_DIR="/Users/poolebu/catwizardMultitenant/catwizard/catwBackend/branches/branchSpringSecurity/"
DIR_MT="$ROOT_DIR"
LIBS_CATW="$ROOT_DIR/backend/java-src/lib"
LIB_SERVLET="/usr/local/apache-tomcat-7.0.32/lib/servlet-api.jar"
ANT_TARGET="allButFlex"
cd $DIR_MT
ant -lib $LIBS_CATW -lib $LIB_SERVLET $ANT_TARGET
This is one of the many dependency errors I´m getting
[ant:javac] /Users/poolebu/catwizardMultitenant/catwizard/catwBackend/branches/branchSpringSecurity/backend/java-src/catw-common/src/com/bamboo/common/factory/SpringFactory.java:5: error: package flex.messaging does not exist
[ant:javac] import flex.messaging.FlexFactory;
[ant:javac] ^
Related
The path to my project is /project/
My build file structure is src/main/package/subpackage/Class.java
My test file structure is src/test/package/subpackage/Test.java
I would like my compiled code to be in bin/main/package/subpackage/Class.class
Compiled test code in bin/test/package/subpackage/Test.class
My pom.xml has the entry
<build>
<sourceDirectory>${project.basedir}/src/main</sourceDirectory>
<testSourceDirectory>${project.basedir}/src/test</testSourceDirectory>
<outputDirectory>${project.basedir}/bin/main</outputDirectory>
<testOutputDirectory>${project.basedir}/bin/test</testOutputDirectory>
<finalName>${project.artifactId}-${project.version}</finalName>
</build>
Running mvn clean install causes the following.
Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:2.6:resources (default-resources) on project Hello-Maven: Error loading property file '/project/': /project (Is a directory) -> [Help 1]
...
[Help 1] https://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
Now I've tried the link, but it suggest that it's an issue with the plugins.
However, commenting this block out, and running mvn clean install again returns an almost empty jar file inside /project/target/Hello-Maven-1.0-SNAPSHOT.jar, containing only the pom and the manifest. Additionally, there aren't any plugins, only dependencies: junit and javafx.
EDIT: I realize that plugins specifically for running maven but finding information over why the error happens for "install" is difficult at best.
I've got a custom Ant task that I'm using successfully from gradle on my local machine:
task fetchRelMod {
doLast {
println 'Fetching the RelMod'
ant.taskdef(name:'relmod',
classpath:'retrievePBSInfo.jar:hsjt400-4-9.jar',
classname:"com.myco.ant.tasks.RetrievePBSRelModString")
ant.relmod(user:project.ext.props.getProperty('fetchrelmod.username'),
password:project.ext.props.getProperty('fetchrelmod.password'),
prodCode:project.ext.props.getProperty('profile.pbs.product.code'),
branch:project.ext.props.getProperty('profile.pbs.branch'),
state:project.ext.props.getProperty('profile.pbs.relmod.selector'))
project.ext.set('iseries_relmod',ant.relmodStub)
project.ext.set('iseries_relmodAndDate', ant.relmod)
}
}
I've got the jar files sitting next to build.gradle for now, out of simplicity... they exist in the same location on the build server. Works great locally. When I run my build from my build server (either through Jenkins or going on the box and running Gradle directly), I get the following:
sudo /var/lib/jenkins/tools/hudson.plugins.gradle.GradleInstallation/gradle214/bin/gradle all -DisQUABuild=true
Building My App
Loading Properties files...
QUA Build. Using build-qua.props
:fetchRelMod
Fetching the RelMod
:fetchRelMod FAILED
FAILURE: Build failed with an exception.
* Where:
Build file '/var/lib/jenkins/workspace/MyApp/build.gradle' line: 141
* What went wrong:
Execution failed for task ':fetchRelMod'.
> taskdef class com.myco.ant.tasks.RetrievePBSRelModString cannot be found
using the classloader AntClassLoader[/var/lib/jenkins/workspace/myApp/hsjt400-4-9.jar]
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
BUILD FAILED
Total time: 3.104 secs
What concerns me is that there are two jar files in the classpath and it only mentions one in the error. Does anyone have any ideas as to what might be going on?
I would like to:
use the Frege programming language to write a simple "Hello World" piece of code,
then using the Frege compiler generating the equivalent Java source code,
then building an executable Jar file to run from the command line,
all the previous steps should be "controlled" by Gradle.
I am able to generate the source code (items 1. and 2. from the previous list), but I am not able to specify a "package" structure of the Java source code in output, i.e. I can not see the package Java statement as the first line of code in the generate Java source code. I can specify to the Frege compiler where to put the generated code though (via the -d argument).
I think this is the reason why when building an executable Jar, then launching it, I am seeing similar errors (according to different attempts on Gradle tasks) e.g.: no main manifest attribute.
The Frege source code is saved in a file named HelloFrege.fr, the generated Java source code is in a file named HelloFrege.java (I verified the file contains the expected main method).
Here there's a version of the Gradle "Jar task":
//create a single Jar with all dependencies
task fatJar(type: Jar) {
manifest {
attributes 'Implementation-Title': 'Hello Frege Jar Example',
'Implementation-Version': version,
'Main-Class': 'HelloFrege'
}
baseName = project.name + '-all'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
Here there's another version of the Gradle "Jar" task:
jar {
manifest {
attributes 'Main-Class': 'HelloFrege'
}
}
How can I solve this problem? I would like to avoid to manually add the package reference to the automatically generated Java source code file.
If your module name in Frege is unqualified such as HelloWorld, you will not see the package statement generated in Java. The module name will become the class name and the package will be empty or default package.
If your module name is qualified such as foo.bar.HelloWorld, then foo.bar will be the package name and HelloWorld will be the class name in the generated Java source.
The rule is that the last part of the module name becomes the class name and the qualifiers form the package name in the generated Java source.
I am not sure what gradle can do for you in this regard, but without gradle, the following should at least be possible:
... build your jar, as before ...
jar -uvfe project-all.jar HelloFrege
java -jar project-all.jar # run it
This, of course, is just another way to create a manifest. If this works, then it would be time to investigate why gradle refuses to do it.
Postscriptum: After thinking another minute about what the problem might be, it occurs to me that you may think that the source file name/path has anything to do with the java package name. This is not so in Frege, though it is good practice to have the file path match the package name, and the file base name match the class name (just like in Java). In addition, to remove some confusion, use the module keyword in frege. As explained by Marimuthu, the Java package and class name is derived from the frege module name.
Example:
$ cat Foo.fr
module my.org.Baz where
...
$ java -jar fregec.jar -d bin Foo.fr
This generates the Baz class in package my.org, and creates the class file in bin/my/org/Baz.class
I am posting here my findings so far. The combination of Gradle commands that works for me is the following one (calling it from the command line typing gradle clean generateJavaSrcFromFregeSrc fatJar):
task generateJavaSrcFromFregeSrc {
ant.java(jar:"lib/frege3.21.586-g026e8d7.jar",fork:true) {
arg(value: "-j") // do not run the java compiler
arg(value: "-d")
arg(value: "src/main/java") // the place where to put the generated source code (paired to the -d argument)
arg(value: "src/main/frege/HelloFrege.fr")
}
}
jar {
manifest {
attributes 'Main-Class': 'org.wathever.HelloFrege'
}
}
task fatJar(type: Jar) {
from files(sourceSets.main.output.classesDir)
from files(sourceSets.main.output.resourcesDir)
//from {configurations.compile.collect {zipTree(it)}} // this does not include the autogenerated source code
baseName = project.name + '-fatJar'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
The manifest details need to be specified in the jar block of code, if I specify them in the task fatJar then when running the jar I get no main manifest attribute, in [...].
If I use just the block of code jar with the property from("$projectDir") { include 'lib/**'} to include the Frege jar, then I get errors like java.lang.ClassNotFoundException (I think because the Jar is included as it is and not as a set of .class files).
The folder src/main/java/org/wathever needs to be there before running Gradle (additional info: the Maven convention prefix src/main/java with as a suffix the "Java package" as specified inside the HelloFrege.fr source code: module org.wathever.HelloFrege where)
Some useful details I found:
How to build a fat Jar
Another how to build a fat Jar
An "Hello Frege" example without the Gradle management
The Gradle documentation on how to use the Jar task
My Groovy script depends on some libraries. This is what I have at the top of my script.
#Grapes([
#Grab(group = 'net.sf.json-lib', module = 'json-lib', version = '2.3',
classifier = 'jdk15'),
#Grab(group = 'org.codehaus.groovy.modules.http-builder',
module = 'http-builder', version = '0.7.1'),
#Grab(group = 'commons-cli', module = 'commons-cli', version = '1.2')])
When I run the script from command line using groovy executable, everything works properly. The artefacts get downloaded and the script runs.
However, if I try to execute the same script from Apache Ant using <groovy src="myscript.groovy" fork="true" /> (simplified), the artefacts also get resolved and downloaded but then I get [groovy] Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/cli/ParseException.
The Apache Ant installation uses groovy-all-2.3.6.jar that I have copied from the Groovy installation that I have installed, so they should be pretty much identical.
What am I missing? How can I make the <groovy> task work and use the downloaded jars?
UPDATE I
The issue I believe is that Grape and Ant use different classloaders so the artifacts aren't visible to Ant. Can you try adding this: #GrabConfig(systemClassLoader = true) to your groovy script after the #Grape annotations?
If I do that I get General error during conversion: No suitable ClassLoader found for grab.
UPDATE II
I have also tried this now:
import groovy.grape.Grape;
Grape.grab(group:"commons-cli", module:"commons-cli", version:"1.2", classLoader:this.class.classLoader.rootLoader)
//...
It does not help. I get compile time error then:
[groovy] Exception in thread "main" Script Failed: org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
[groovy] C:\Users\xxx\AppData\Local\Temp\embedded_script_in_2825216891785993632groovy_Ant_task: 18: unable to resolve class groovyx.net.http.HTTPBuilder
[groovy] # line 18, column 1.
[groovy] import groovyx.net.http.HTTPBuilder
[groovy] ^
Get rid of the #Grab and use the static .grab() method Grape offers. It allows you to specify a the rootLoader classloader which Ant can see:
import groovy.grape.Grape;
Grape.grab(group:"commons-cli", module:"commons-cli", version:"1.2", classLoader:this.class.classLoader.rootLoader)
<repeat for rest of #Grab>
I'm trying to create an OSGi wrapper for the newest version of jTDS. I'm trying to add the wrapping process to the existing jTDS build process (Ant-based). I've downloaded the latest bnd.jar and added the following to the jTDS build.xml:
<taskdef resource="aQute/bnd/ant/taskdef.properties" classpath="bnd.jar"/>
<bndwrap trace="true" definitions="${basedir}/bnd" output="${build}/${ant.project.name}-${version}.osgi.jar">
<fileset dir="${build}" includes="*.jar"/>
</bndwrap>
I've also got a very simple bnd definition defined:
version=1.2.6
Export-Package: net.sourceforge.jtds*;version=${version}
Bundle-Version: ${version}
Bundle-Name: net.sourceforge.jtds
When I execute the dist task in Ant, it should be creating a JAR with the proper OSGi manifest. It IS creating another JAR, but the manifest is identical to the original.
If I execute the same wrap directly against the bnd JAR:
java -jar bnd.jar wrap -p bnd\jtds-1.2.6.bnd -o build\jtds-1.2.6.osgi.jar build\jtds-1.2.6.jar
I get the correct OSGi manifest.
What is going wrong during the Ant build?
It seems to be a problem with the latest version of bnd, found here. The Ant WrapTask was retooled some and just doesn't seem to work (maybe it's just misconfigured; documentation hasn't kept up with code).
I dropped in version 1.50.0 instead and everything worked as expected both through the bnd.jar and through Ant.