Deploy JavaFX application with Ant script - ant

I'm trying to generate a executable jar for my JavaFX application with Ant, and the difference between my jar and the one generated by the JavaFX Packager is that the latter include classes from com.javafx.main package.
How can I tell in my Ant script to include these classes in the jar as well ?

The ant file you're using must have the special fx-tasks to deploy the jar, and not the ant built-in jar tasks. Here's a sample ant target for generating a jar with JavaFX:
<target name="jar" depends="compile">
<echo>Creating the main jar file</echo>
<mkdir dir="${distro.dir}" />
<fx:jar destfile="${distro.dir}/main.jar" verbose="true">
<fx:platform javafx="2.1+" j2se="7.0"/>
<fx:application mainClass="${main.class}"/>
<!-- What to include into result jar file?
Everything in the build tree-->
<fileset dir="${classes.dir}"/>
<!-- Define what auxilary resources are needed
These files will go into the manifest file,
where the classpath is defined -->
<fx:resources>
<fx:fileset dir="${distro.dir}" includes="main.jar"/>
<fx:fileset dir="." includes="${lib.dir}/**" type="jar"/>
<fx:fileset dir="." includes="."/>
</fx:resources>
<!-- Make some updates to the Manifest file -->
<manifest>
<attribute name="Implementation-Vendor" value="${app.vendor}"/>
<attribute name="Implementation-Title" value="${app.name}"/>
<attribute name="Implementation-Version" value="1.0"/>
</manifest>
</fx:jar>
</target>
Note, that you must have a taskdef defined somewhere in the script:
<taskdef resource="com/sun/javafx/tools/ant/antlib.xml"
uri="javafx:com.sun.javafx.tools.ant"
classpath="${javafx.sdk.path}/lib/ant-javafx.jar"/>
and the project tag must have the fx xmlns reference:
<project name = "MyProject" default ="compile" xmlns:fx="javafx:com.sun.javafx.tools.ant">
The generated jar file should now include the classes from javafx.main and the manifest will include them as an entry point into the application. More info:
http://docs.oracle.com/javafx/2/deployment/packaging.htm

Related

ANT: ways to include libraries and license issues

I have been trying to use Ant to compile and ready a project for distribution. I have encountered several problems along the way that I have been finally able to solve but the solution leaves me very unsatisfied. First, let me explain the set-up of the project and its dependencies.
I have a project, lets call it Primary which depends on a couple of libraries such as the fantastic Guava. It also depends on another project of mine, lets call it Secondary. The Secondary project also features some dependencies, for example, JDOM2. I have referenced the Jar I build with Ant in Primary.
Let me give you the interesting bits of the build.xml so you can get a picture of what I am doing:
<project name="Primary" default="all" basedir=".">
<property name='build' location='dist' />
<property name='application.version' value='1.0'/>
<property name='application.name' value='Primary'/>
<property name='distribution' value='${application.name}-${application.version}'/>
<path id='compile.classpath'>
<fileset dir='libs'>
<include name='*.jar'/>
</fileset>
</path>
<target name='compile' description='Compile source files.'>
<javac includeantruntime="false" srcdir="src" destdir="bin">
<classpath refid='compile.classpath'/>
</javac>
<target>
<target name='jar' description='Create a jar file for distribution.' depends="compile">
<jar destfile='${build}/${distribution}.jar'>
<fileset dir="bin"/>
<zipgroupfileset dir="libs" includes="*.jar"/>
</jar>
</target>
The Secodnary project's build.xml is nearly identical except that it features a manifest as it needs to run:
<target name='jar' description='Create a jar file for distribution.' depends="compile">
<jar destfile='${dist}/${distribution}.jar' basedir="${build}" >
<fileset dir="${build}"/>
<zipgroupfileset dir="libs" includes="*.jar"/>
<manifest>
<attribute name="Main-Class" value="lu.tudor.ssi.kiss.climate.ClimateChange"/>
</manifest>
</jar>
</target>
After I got it working, trying for many hours to not include that dependencies as class files but as Jars, I don't have the time or insight to go back and try to figure out what I did wrong. Furthermore, I believe that including these libraries as class files is bad practice as it could give rise to licensing issues while not packaging them and merely including them in a directory along the build Jar would most probably not (And if it would you could choose not to distribute them yourself).
I think my inability to correctly assemble the class path, I always received NoClassDefFoundError for classes or libraries in the Primary project when launching Second's Jar, is that I am not very experienced with Ant. Would I require to specify a class path for both projects? Specifying the class path as . should have allowed me to simply add all dependencies to the same folder as Secondary's Jar, should it not?
You may use the MANIFEST.MF "Class-Path: " to cross-reference your jars.
If they are all in the same directory this will probably work as follows (using it in both projects!):
<target name='jar' description='Create a jar file for distribution.' depends="compile">
<pathconvert property="manifest.classpath" pathsep=" ">
<path refid="compile.classpath" />
<flattenmapper />
</pathconvert>
<jar destfile='${build}/${distribution}.jar'>
<fileset dir="bin"/>
<manifest>
<attribute name="Class-Path" value="${manifest.classpath}"/>
</manifest>
</jar>
</target>
This way you can tell the java runtime environment that your jar needs others to work, expecting them to be in the same directory as the jar you are trying to run.
As a result your primary.jar should have secondary.jar in it's classpath and secondary.jar should have guava.jar in it's classpath.
Another way to create the string may be ants manifestclasspath task (https://ant.apache.org/manual/Tasks/manifestclasspath.html) that can handle subdirectories.
If you are goin to use more and more libraries, you may want to have a closer look at ivy or even maven.

How to include an optional manifest in an ant jar taks?

<jar destfile="somefile" manifest="META-INF/MANIFEST.MF">
This script runs for multiple projects. Some of the projects have a manifest file, others don't. Build fails on a project that does not have a manifest file.
Is there a way to configure this jar task, so that ant uses project manifest file if it exists and generates a manifest file for a jarred project that doesn't have its own manifest?
Here's a sample I created. This has two jar tasks: jar and jar1. One uses the if check and the other the unless check. The ant target 'all' calls both, but only 1 should run. It checks if the manifest file exsts and if so uses that file, otherwise you can create a local in the jar1 task.
If you want to have only the 1 jar target, then you may need to use the Ant-Contrib tasks and use the tag. Here is a good link to review for this too.
<project name="StackOverflow" basedir="." default="all">
<property name="src.dir" value="${basedir}/src"/>
<property name="build.dir" value="${basedir}/build"/>
<property name="classes.dir" value="${build.dir}/classes"/>
<target name="all" depends="compile,jar,jar1"/>
<target name="check-manifest">
<available file="META-INF/MANIFEST.MF" property="manifest.present"/>
</target>
<target name="jar" depends="check-manifest" if="manifest.present">
<echo>Using existing manifest.mf</echo>
<jar destfile="hello.jar" manifest="META-INF/MANIFEST"/>
</target>
<target name="jar1" depends="check-manifest" unless="manifest.present">
<echo>creating local manifest</echo>
<jar destfile="hello.jar">
<manifest>
<attribute name="Built-By" value="${user.name}"/>
<attribute name="Permissions" value="all-permissions"/>
<attribute name="Codebase" value="*"/>
</manifest>
<fileset dir="${classes.dir}">
<include name="**/*.*"/>
</fileset>
</jar>
</target>
</project>

Using Ant/Ivy to create pom.xml and pom.properties and embedding them into the jar/war file

We use Ant with Ivy and I'd like to embed in our created jars and wars the pom.xml and the pom.properties file just as you see if you used Maven. Creating a pom.xml from the ivy.xml file is pretty simple with the <ivy:makepom> task. Getting the artifactId and the gorupId can be done via the <xmlproperty> task. However, how do I create the pom.properties file. Is that necessary?
Okay, while going through the documentation, I found it was a lot easier than I thought. Ivy generates a lot of properties which can be used. I also found that the pom.xml file only contains the groupId, artifactId and the version, so it's not that tough to generate.
Here's what I did:
<target name="package" depends="compile">
<!-- Make the pom.xml -->
<ivy:makepom ivyfile="${ivy.resolved.file}"
pomfile="${target.dir}/pom.xml"/>
<!-- Make the pom.properties file -->
<echo file="${target.dir}/pom.properties">
# Generated by Maven NOT!
# ${build.date}
version=${ivy.revision}
groupId="${ivy.organisation}
artifactId="${ivy.module}
</echo>
<!-- Build your JAR or whatever -->
<jar destfile="${target.dir}/{ant.project.name}.jar"
basedir="${main.destdir}">
<manifest>
<section name="Build-Information">
<attribute name="Project" value="${env.JOB_NAME}"/>
<attribute name="Build-Number" value="${env.BUILD_NUMBER}"/>
<attribute name="Build-Date" value="${build.date}"/>
</section>
</manifest>
<zipfileset dir="${target.dir}"
prefix="$META-INF/maven/${ivy.organisation}/${ivy.module}">
<include name="pom.xml"/>
<include name="pom.properties"/>
</zipfileset>
</jar>
</target>
This helps make using Ivy pretty compatible with Maven.

generate jars with source code using Ant

I use ant for creating .jar files in Eclipse.
I need to generate jar for my project which also contains source code along with the class file. How do we do it?
Another question: what is a debug jar and how to create it using ant? (have heard about it somewhere and trying to relate them both)
I would modify your jar task to include multiple filesets; one for the classes and one for the source files.
<jar destfile="${target.dir}/my-app.jar">
<fileset dir="${target.dir}/classes" />
<fileset dir="${src.dir}" includes="**/*.java"/>
</jar>
Packaging should be treated as a separate concern from compiling. This will give you more flexibility. For example, you may want to add other filesets to the jar (e.g. properties files), or you may want to package your sources in a jar file that is separate from your class files.
Simply copy the source files into the directory you're using for your jar creation. I've done it like this (notice the copy inside compile):
<?xml version="1.0" encoding="utf-8" ?>
<project name="project" default="jar" basedir=".">
<target name="compile" description="Compile source">
<mkdir dir="bin" />
<javac srcdir="src" includes="**" destdir="bin" (other compilation stuff here) />
<copy todir="bin">
<fileset dir="src" />
</copy>
</target>
<target name="jar" description="Package into JAR" depends="compile">
<jar destfile="project.jar" basedir="bin" compress="true" />
</target>
</project>

Location of xsd for ant ivy lib "antlib:org.apache.ivy.ant" for IDE autocomplete with xsd?

I want create Ivy Ant tasks in xml editor in IDE (Intellij iDEA) with autocomplete based on xsd , but I cannot find xsd for register XML namespace xmlns:ivy="antlib:org.apache.ivy.ant"
Where I can find it?
I just copied the ivy jar to INTELLIJ_HOME/lib/ant and now intellij can resolve the ivy tasks.
Or import this ant file to your ant project, its actually the first ivy example in ivy documentation, make sure to always depend on install-ivy target, add your ant file to idea in the ant build window and you dont even have to install ivy and idea recognizes ivy tasks.
<property name="ivy.jar.dir" value="${user.home}/.ivy2/jars" />
<property name="ivy.jar.file" value="${ivy.jar.dir}/ivy.jar" />
<property name="ivy.install.version" value="2.2.0" />
<target name="check-ivy-installed" unless="INTERN-ivy.jar.exists">
<available property="INTERN-ivy.jar.exists" file="${ivy.jar.file}"/>
</target>
<target name="download-ivy" depends="check-ivy-installed" unless="INTERN-ivy.jar.exists">
<echo message="downloading and installing ivy"/>
<mkdir dir="${ivy.jar.dir}"/>
<!-- download Ivy from web site so that it can be used even without any special installation -->
<get src="http://repo1.maven.org/maven2/org/apache/ivy/ivy/${ivy.install.version}/ivy-${ivy.install.version}.jar"
dest="${ivy.jar.file}" usetimestamp="true"/>
<echo message="ivy installed"/>
</target>
<!-- =================================
target: install-ivy
this target is not necessary if you put ivy.jar in your ant lib directory
if you already have ivy in your ant lib, you can simply remove this
target and the dependency the 'go' target has on it
================================= -->
<target name="install-ivy" depends="download-ivy" description="--> install ivy">
<!-- try to load ivy here from local ivy dir, in case the user has not already dropped
it into ant's lib dir (note that the latter copy will always take precedence).
We will not fail as long as local lib dir exists (it may be empty) and
ivy is in at least one of ant's lib dir or the local lib dir. -->
<echo message="Installing ivy"/>
<path id="ivy.lib.path">
<fileset dir="${ivy.jar.dir}" includes="*.jar"/>
</path>
<taskdef resource="org/apache/ivy/ant/antlib.xml"
uri="antlib:org.apache.ivy.ant" classpathref="ivy.lib.path"/>
</target>
To complete Shalom's answer, the location where to add the ivy.jar for the IntelliJ IDEA Community Edition is INTELLIJ_HOME/lib/ant/lib (one more folder to go).
Maybe it also apply to the full version.
might be, there was no xsd in the past time this discussion started, but at least since may 2011 the ivy scheme is well documented at
http://ant.apache.org/ivy/schemas/ivy.xsd
which is linked right from the documentation in http://ant.apache.org/ivy/
so, to start over using the scheme, you just need:
<?xml version="1.0" encoding="UTF-8"?>
<project name="yourproject"
xmlns:ivy="antlib:org.apache.ivy.ant"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ant.apache.org/ivy/schemas/ivy.xsd"
>
<!-- … -->
I guess this discussion might help you. It appears that there is no xsd for the ivy ant tasks, but Eclipse does autocomplete.
yes, no xsd for ivy ant tasks avialable. but i found the way to make autocomplete in Intellij IDEA
in ant build file need to define additional task:
<property name="ivy.jar.dir" value="C:/Apache/apache-ivy-2.2.0/"/>
<taskdef resource="org/apache/ivy/ant/antlib.xml"
uri="antlib:org.apache.ivy.ant">
<classpath>
<fileset dir="${ivy.jar.dir}" includes="*.jar"/>
</classpath>
</taskdef>
XML plugin for jEdit defines AntCompleteTask (ant task) that produces an xml file called ant-complete.xml. The resulting file looks as follows:
<element-list>
<!-- ... -->
<element name="classpath"
content="(fileset|dirset|extdirs|existing|filelist|pathelement|path)">
<attribute name="id" type="ID" />
<attribute name="location" type="CDATA" />
<attribute name="cache" type="(true|false|on|off|yes|no)" />
<attribute name="refid" type="CDATA" />
<attribute name="description" type="CDATA" />
<attribute name="path" type="CDATA" />
</element>
<!-- ... -->
The generated file may be downloaded as XML plugin archive. Open XML.jar and browse to xml/completion directory. It's syntax is defined in xml-completion-info.dtd.
The task code does not contain an explicit license, but it's at least GPL. Anyway you probably don't need to distribute that task, only to use it and this doesn't require any license.
I can't assess the usability of the resulting xml file, but jEdit uses it for autocompletion.

Resources