I need to create an installer using gradle and izpack through gradle-izpack-plugin, but every time I run gradle build, it points out that the custom action .jar that are defined in izpack-install.xml are not being found , even though I put them in the correct folder. I have the same project written in Ant, and it works normally, but even trying to run the Ant project through gradle, it shows the same error, the same way it happens when I use the gradle-izpack-plugin. Am I doing something wrong or is there any additional configuration to be done in gradle?
build.gradle
(I can only post the tasks because its from my work)
izPackCreateInstaller.dependsOn('customActions')
izpack{
baseDir = file("target")
installFile = file('IzPack-install.xml')
outputFile = file(project.jarName)
compression = 'deflate'
compressionLevel = 9
}
task customActions(type: Copy, dependsOn: ['jar']){
duplicatesStrategy=DuplicatesStrategy.EXCLUDE
into 'bin'
into('/customActions'){
from 'build/libs'
rename('installer.jar', 'MyTestInstallerListener.jar')
}
into('/customActions'){
from 'build/libs'
rename('installer.jar', 'MyTestUninstallerListener.jar')
}
}
The error :
[org.gradle.api.internal.project.ant.AntLoggingAdapter] Couldn't load Resource bin/customActions/MyTestInstallerListener.jar
[org.gradle.api.internal.project.ant.AntLoggingAdapter] Couldn't load Resource bin/customActions/MyTestUninstallerListener.jar
directory structure
I already check and the customActions task is running before izPackCreateInstaller task
Related
Hi I have a tar task that I made after looking at numerous methods and some SO posts.
task buildDist(type: Tar, dependsOn: jar) {
print 'here'
archiveName = 'xyz-' + version
destinationDir = file('build/dist')
extension = 'tar.gz'
compression = Compression.GZIP
from 'build/libs'
include 'xyz.jar'
}
buildDist.mustRunAfter jar
I have the java plugin applied and the jar task makes the xyz.jar file available under build/libs. The build/dist directory does not exist yet, but I tried new File("build/dist") as well. That did not work either - I even pointed it to the build directory that exists - doesn't work. I run the entire script with /gradlew clean build. The print in the above code does print.
I am making a few assumptions here as you didn't post the output from running Gradle.
The build task is just a normal Gradle task that doesn't do anything by itself. Instead, it depends on other tasks. If you create your own custom task and you like to have it included when executing build, you have to add a dependency to it. If this is not the problem and you have actually done this, please give some more details as to what makes it "not work" when you run build.
If you want to test your task in isolation (e.g. to make sure it works correctly without running unit tests or whatever else that is unrelated), just run gradlew cleanBuildDist buildDist.
A note about the 'print' statement - it executes doing the configuration phase, but this doesn't mean you can use it to test if the task actually executes. In fact, it will most likely print no matter what task you execute. If you wanted to print something on execution time, you would have to put it in a doLast block.
There is a few other things you should change as well:
It is not a good practice to use relative references. Instead, use the buildDir property to get an absolute reference to the build directory.
Don't use deprecated methods like archiveName and destinationDir. Use archiveFileName and destinationDirectory instead.
The extension property is also deprecated, but it is ignored if you set the full name of the archive yourself. So just remove it. This also means you are missing the extension on the full name.
The from and include is a little fragile. Just use from jar.archivePath if you only want to gzip your application jar.
Example:
task buildDist(type: Tar, dependsOn: jar) {
archiveFileName = "${jar.baseName}-${version}.tar.gz"
destinationDirectory = file("$buildDir/dist")
compression = Compression.GZIP
from jar.archivePath
}
build.dependsOn buildDist
Lastly, if your intention is to create a distribution of your application that is runnable on its own (with all required dependencies), you should consider using the distribution plugin and perhaps also the application plugin.
I am trying to execute parallel tests through the use of Maven InvocationRequest, Invoker, and InvocationResult components which are a part of maven-invoker dependency added into the pom.
Ultimately, I want Jenkins to run an executable jar which in turn executes the parallel tests. The code to programmatically invoke Maven to run the tests looks like this:
InvocationRequest request = new DefaultInvocationRequest();
request.setPomFile( new File("pom.xml") ); //pom is in the root level of the project
request.setShowErrors(true);
List<String> goalList = Arrays.asList("clean","install");
request.setGoals( goalList );
Invoker invoker = new DefaultInvoker();
invoker.setMavenHome(new File(System.getenv("MAVEN_HOME")));
InvocationResult result = null;
try {
result = invoker.execute( request );
} catch (MavenInvocationException e) {
e.printStackTrace();
}
if ( result.getExitCode() != 0 )
{
throw new IllegalStateException( "Build failed." );
}
This code lives in the main class (i.e., public static void main(String[] args) ) which serves as the entry point when running the compiled executable JAR. The idea is that Jenkins will fire off something akin to this -->> "java -jar MyCompiledTests.jar" ... and this would run the code above which allows the tests to run in parallel.
This works so long as I use the pom location where the original project files reside. But, I am needing to compile a JAR which will live on an integration server and would be run by Jenkins daily (I do this with the current battery of tests but currently they all run in series). It seems that when I build the executable JAR (using maven-assembly-plugin), the pom file is not added to it.
So, the code above which needs to access the pom will return an error saying it cannot find the pom. To remedy that, I manually added the pom file to sit alongside the JAR in the given remote folder, but then when running this arrangement, I receive an error concerning the absence of the Features folder.
This error happens when the Cucumber-JVM-parallel plugin is reached during pom execution. Receiving this error stems from the fact that the pom file is now being read but the various path references within this plugin are not recognized because they are relative to the location of the original project folders in Eclipse and not the new remote folder location alongside the executable JAR.
Again, I can run things in Eclipse just fine and can even run the compiled executable JAR as long as I can point to the pom file which lives at the original project folder.
The Question:
How does one compile and run a standalone executable JAR so that it
can invoke Maven to run the parallel tests set up by
Cucumber-JVM-parallel-plugin?
How should the pom be referenced in the code above differently?
Can the pom be wrapped into the executable JAR when it is compiled...or should it be?
Is there a more elegant way to compile and run the executable JAR
I have searched far and wide, but either I am not seeing the answer right in front of me, or my intended goals for this executable JAR are unachievable given the current state of maven technologies.
Currently, my build.gradle has a dependency on an external library built with Ant. To accomplish building the library, I followed the advice here and created a task which builds the external library, and copies it to the libs/ folder.
The task is called as part of a dependency:
build.gradle
dependencies {
compile fileTree('libs') {
include '*.jar'
builtBy 'myTask'
}
}
task myTask (type: GradleBuild) { GradleBuild antBuild ->
antBuild.buildFile('external-stub.gradle')
antBuild.tasks = ['clean', 'ivy.check', 'ivy.download', 'ivy.task', 'ivy',
'init', 'mergeCode', 'compile', 'jar', 'copyJarsToProject']
}
However, when the compile actually runs, the library I just built and copied in is not included in the dependencies, as evidenced by a whole lot of compilation errors.
Am I including the library the wrong way?
The full build.gradle and associated files are over at Github, and I've linked to the specific commit I'm having issues with: Source Repository
Alright, took me a while to get a build I was happy with. But, here's what was changed.
The actual build of the JAR was built using the same style, but moved to the external project (so that the main build project wasn't reaching across to it). I'll give an in-depth explanation below, but the commits are here and here. These are in order.
Basically, we export the jar as an artifact that other projects can depend on, rather than copying over the Jar ourselves. This way, the Ant build runs and other projects can see the Jar we just created. This is the end of the first commit. In the second commit, the task outputs are marked as needing to be regenerated only if the Jar does not exist. This was due to the fact that whenever I tried to build the app, it would take minutes to regen the Jar, and then have to repackage everything else as well. The code is below:
build.gradle External Project
configurations {
buildJSword
}
task doBuildJSword (type: GradleBuild) {
buildFile = 'jsword-stub.gradle'
tasks = ['clean', 'ivy.check', 'ivy.download', 'ivy.task', 'ivy',
'init', 'mergeCode', 'compile', 'jar'] //, 'copyJarsToMinimalBible']
ext.outputJar = file('distribution/jsword.jar')
outputs.upToDateWhen {
ext.outputJar.exists()
}
}
artifacts {
buildJSword(doBuildJSword.ext.outputJar) {
builtBy doBuildJSword
}
}
Then, the main project just has to add this project as a compile-time dependency:
build.gradle Main Project
compile project(path: ':jsword-minimalbible', configuration: 'buildJSword')
Hope this is helpful for anyone with a similar issue, let me know if you have questions!
Note: The build currently does not clean itself properly, so if you change any code in the external project, you need to delete the external Jar for everything to regenerate itself correctly.
I write a custom gradle plugin where I would like to copy a specific file from a jar inside the classpath into the buildDir. I played around in a sandbox project and got this solution working:
task copyFile(type: Copy) {
from zipTree(project.configurations.compile.filter{it.name.startsWith('spring-webmvc')}.singleFile)
include "overview.html"
into project.buildDir
}
but if copy it into my plugin:
project.task(type: Copy, "copyFile") {
from zipTree(project.configurations.compile.filter{it.name.startsWith('spring-webmvc')}.singleFile)
include "overview.html"
into project.buildDir
}
I got the error:
* What went wrong:
A problem occurred evaluating root project 'gradle-springdoc-plugin-test'.
> Could not find method zipTree() for arguments [/Users/blackhacker/.gradle/caches/artifacts-26/filestore/org.springframework/spring-webmvc/4.0.0.RELEASE/jar/a82202c4d09d684a8d52ade479c0e508d904700b/spring-webmvc-4.0.0.RELEASE.jar] on task ':copyFile'.
The result of
println project.configurations.compile.filter{it.name.startsWith('spring-webmvc')}.singleFile.class
is
class java.io.File
What I am doing wrong?
Unlike a build script, a plugin does not have an implicit project context (unless you give it one). Hence you'll have to use project.task rather than task, project.zipTree rather than zipTree, project.file rather than file, etc.
PS: In your case, it's important to use project.zipTree { ... } (note the curly braces) to defer searching for the file until the Zip contents are actually requested. Otherwise you risk slowing down each build invocation (even ones that never execute copyFile) and, if the file is being produced by the same build, even build failures (because the configuration is resolved before the file has been added).
I have a gradle project with multiple packages. After the build, each package generates its jar files in build/libs. The external jar dependencies are pulled into ~/.gradle. I would now like to run the service locally from the commandline with the appropriate classpath. For this purpose, I am writing a script that constructs the classpath. The problem is that the script does not understand all the external dependencies and hence cannot construct the classpath. Is there a way for gradle to help with this? Ideally, I would like to dump all the dependencies into a folder at the end of the build.
Firstly, i would suggest using the application plugin if you can, since it takes care of this already.
If you want to dump the classpath to a file yourself, the simplest way is something like:
task writeClasspath << {
buildDir.mkdirs()
new File(buildDir, "classpath.txt").text = configurations.runtime.asPath + "\n"
}
If you want to actually copy all the libraries on the classpath into a directory, you can do:
task copyDependencies(type: Copy) {
from configurations.runtime
into new File(buildDir, "dependencies")
}
You could try something like this in your build script:
// add an action to the build task that creates a startup shell script
build << {
File script = file('start.sh')
script.withPrintWriter {
it.println '#!/bin/sh'
it.println "java -cp ${getRuntimeClasspath()} com.example.Main \"\$#\""
}
// make it executable
ant.chmod(file: script.absolutePath, perm: 'u+x')
}
String getRuntimeClasspath() {
sourceSets.main.runtimeClasspath.collect { it.absolutePath }.join(':')
}