I'm working around "Self-Contained Application" generation using Java Packager Tool. By default, the '.exe' bundle is installed under "C:\Program Files (x86)" but I would like install it to a custom location : "C:\MyApp" for example.
To generate my bundle, I'm using an Ant Task inside a Maven build :
<target xmlns:fx="javafx:com.sun.javafx.tools.ant">
<property name="jre.dir" value="${env.JAVA_HOME}/jre" />
<property name="version" value="0.0.3" />
<taskdef resource="com/sun/javafx/tools/ant/antlib.xml"
uri="javafx:com.sun.javafx.tools.ant" classpath="${env.JAVA_HOME}/lib/ant-javafx.jar" />
<echo message="// ----------------------------------- //" />
<echo message="// START JAVAPACKAGER ANT TASK //" />
<echo message="// ----------------------------------- //" />
<fx:deploy nativeBundles="exe" outdir="${basedir}/packager"
outfile="MyApp_${version}">
<fx:application name="MyApp" mainClass="com.myfirm.myapp.bootstrap.BootstrapMain">
<fx:argument>-bundlesDir=./bundles/</fx:argument>
</fx:application>
<fx:resources>
<fx:fileset dir="${project.basedir}/target"
includes="${project.name}-${project.version}-jar-with-dependencies.jar" />
<fx:fileset dir="${project.basedir}" includes="bundles/*.jar" />
</fx:resources>
<fx:info title="MyApp ${version}" vendor="MyFirm">
<fx:icon href="${project.basedir}/myapp.ico" kind="default" width="32" height="32" depth="8" />
</fx:info>
<fx:preferences install="true" shortcut="true" />
<fx:platform basedir="${jre.dir}"/>
</fx:deploy>
</target>
Has anybody work around this ? And could tell me more about how to configure more precisely the generated native bundle ?
Thanks by advance.
EDIT
Under Windows, I have found a way to do it : by editing file com\oracle\tools\packager\windows\template.iss in jar %JAVA_HOME%\lib\ant-javafx.jar. But this solution seems to be ugly and not portable ! So I'm now looking for a way to override it in my ant task...
For extra documentation, what Tib Us did was edit %JAVA_HOME%\lib\ant-javafx.jar. You can use 7-Zip (or others) to open that jar file and update it's contents.
In com\oracle\tools\packager\windows\template.iss, change this line:
DefaultDirName=APPLICATION_INSTALL_ROOT\APPLICATION_NAME
To:
DefaultDirName={pf}\APPLICATION_NAME
{pf} is a Inno Setup constant pointing to 32-bit or 64-bit Program Files folder. See Inno Setup Help.
If you'd like to install in Program Files, then it is helpful to change:
PrivilegesRequired=APPLICATION_INSTALL_PRIVILEGE
To:
PrivilegesRequired=admin
Also, if your program is going to be used by non-admin users and will be writing to its folder in Program Files, then you'll need some special folder permissions. Here is some background on permissions for an app running in Program Files.
You might also like to add this, to ensure that the new install location is used:
UsePreviousAppDir=No
This solution isn't ideal, but is better than nothing.
Getting the template from the jar file is fine—or download it here—but you don't need to edit it where it is.
Once you have that template, you can just use it as a drop-in resource. All the variables that look like SOME_VARIABLE, that is, upper case and which use underscores, will still be replaced by the javapackager.
This solution is much more portable because it doesn't involve editing the JDK; just include your template in package/windows/ as YourAppName.iss.
User Option -BinstalldirChooser=true
Related
I have JAVA library that I am working on and I am using Ant build system, I am trying to generate a .jar file from and using in another application, what I am trying to do is to enable some specific ENV variables only in Debug build and have them disabled in production/release, and I was wondering how can I achieve that?
In my build.xml I have a property called "debug", which is boolean.
In C/C++ You have the NDEBUG macros where you can define what you will exclude/include in debug mode,
is there something similar in JAVA?
I have tried to read Ant documentation, I see that they use properties but the documentation doesn't state exactly how you can pass those properties into the source code, In fact, I tried to do that but with no success.
As mentioned by #Joachim Sauer above, Java does not feature conditional compilation. You can argue either way for this being a good feature, but it's not available.
What can you do, then?
One method you can use is to write information into the jar's manifest.
For example, you could include the build version and your debug flag like so:
<jar destfile="my.jar" basedir="build/classes">
<manifest>
<attribute name="Package-Title" value="My Package Title" />
<attribute name="Package-Version" value="${build.current.version}" />
<attribute name="Debug" value="${debug}" />
</manifest>
</jar>
Then, in your code, you would attempt to read your own jar's manifest: Reading my own Jar's Manifest
Another simpler option might be to include a properties file in your jar, and just read that. You can use the ant task 'echo' to write out a properties file before the jar task:
<echo file="build/classes/my.properties" encoding="ISO-8859-1" append="false">
Package-Title: ${package-title}
Package-Version: ${build.current.version}
com.example.app.debug=${debug}
</echo>
Then, you can just open "my.properties" in the code as a resource, and use that.
I have an ant target that copies a file from one location to another, say it is defined in the build.xml as:
${project}/some-component-ABC/lib/whatever.jar
But on the file system the actual path is
${project}/some-component-abc/lib/whatever.jar
No uppercase ABC in some-component-abc on the fliesystem...
This path will resolve in Windows (7) but not in Linux?
Why?
I'll figure out what to do with it, just wanted some background why the functional difference.
Per the following article: https://ubuntuforums.org/showthread.php?t=1227827
Linux is written in C, which is case sensitive. It makes for faster sorting.
Ant doesn't do anything fancy with paths - it just delegates down to the underlying filesystem. Windows' filesystem is not case-sensitive, while any linux filesystem I can think of is. So, in windows, some-component-abc and some-component-ABC are the same directory, while in linux they would not be.
As others have mentioned, for the most part Ant just stores strings for everything and relies on the OS's filesystem when it actually comes time to perform filesystem operations, so you will run into differences like this when running scripts in Linux vs Windows.
However, Ant does have tasks that manipulate path-like strings, and these can be used to groom references to files prior to using them. Here's an example:
~/test $ ls -1
build.xml
FILE
build.xml:
<project>
<pathconvert property="file">
<fileset dir="${basedir}" includes="file" casesensitive="false" />
</pathconvert>
<echo message="${file}" />
</project>
Output:
[echo] /home/me/test/FILE
Alternative approach (will return a path-like string relative to the fileset's dir attribute):
<project>
<fileset dir="${basedir}" includes="file" casesensitive="false" id="filepath" />
<property name="file" refid="filepath" />
<echo message="${file}" />
</project>
Output:
[echo] FILE
I was experimenting with the recipe for creating a custom VM pack, the motivation was to put our 3rd party libs in some "blessed" JRE distro's /lib/ext folder and zip it up as vm.zip (no compression, no paths) and then package that up with a properties file into another zip.
A VM file created that way shows up in the IA options for building, but the resulting installer.exe launches with a message that it could not find main class. The same project built with one of the vanilla JVM packs from IA works fine, so it must be something in the way I am creating my custom VM.
I also tried the File -> Create VM pack option from the UI, which likewise, gives me an error. Has anyone done this successfully, and if so, what zip tool did you use? (7z here..)
thanks for any insight!
You can use ant to build vm pack.
<?xml version="1.0" encoding="UTF-8"?>
<project name="build_vm" default="default">
<property name="buildTmpDir" value="Path_to_your_jre"/>
<target name="default">
<zip destfile="${buildTmpDir}/vm.zip"
compress="false">
<fileset dir="${buildTmpDir}/jre/"/>
</zip>
<zip destfile="${buildTmpDir}/jre1.8.0.vm">
<fileset dir="${buildTmpDir}/" includes="vm.zip"/>
<fileset dir="${buildTmpDir}/" includes="vm.properties"/>
</zip>
</target>
</project>
Pay attention that ${buildTmpDir}/jre must contain bin and lib folders.
The contents of vm.properties file have to look like this
vm.platform=windows
vm.platform.flavor=win32
vm.name=v1.8.0 Windows i386
vm.exe.path=bin\\java.exe
I have to copy a file if a property is set in ant target, but I always get an error for this code:
<condition property="component.is.x">
<equals arg1="${COMPONENT_ID}" arg2="x" />
</condition>
<target name="copyschemaparamsfile" if="sql.file.present" >
<if>
<equals arg1="${component.is.x}" arg2="true" />
<then>
<copy file="${in.root}/schema/${COMPONENT_ID}-schema.sql"
tofile="${tmp.dir}/${COMPONENT_ID}/x/schema/schema.sql"
failonerror="false" />
</then>
<else>
<copy file="${inf.root}/schema/${COMPONENT_ID}-schema.sql"
tofile="${tmp.dir}/${COMPONENT_ID}/${COMPONENT_ID}/schema/schema.sql" failonerror="false" />
</else>
</if>
</target>
Error is:
Ant could not find the task or a class this task relies upon.
This is common and has a number of causes; the usual
solutions are to read the manual pages then download and
install needed JAR files, or fix the build file:
- You have misspelt 'if'.
Fix: check your spelling.
- The task needs an external JAR file to execute
and this is not found at the right place in the classpath.
Fix: check the documentation for dependencies.
Fix: declare the task.
- The task is an Ant optional task and the JAR file and/or libraries
implementing the functionality were not found at the time you
yourself built your installation of Ant from the Ant sources.
Fix: Look in the ANT_HOME/lib for the 'ant-' JAR corresponding to the
task and make sure it contains more than merely a META-INF/MANIFEST.MF.
If all it contains is the manifest, then rebuild Ant with the needed
libraries present in ${ant.home}/lib/optional/ , or alternatively,
download a pre-built release version from apache.org
- The build file was written for a later version of Ant
Fix: upgrade to at least the latest release version of Ant
- The task is not an Ant core or optional task
and needs to be declared using <taskdef>.
- You are attempting to use a task defined using
<presetdef> or <macrodef> but have spelt wrong or not
defined it at the point of use
Remember that for JAR files to be visible to Ant tasks implemented
in ANT_HOME/lib, the files must be in the same directory or on the
classpath
I am always getting above error when I execute. Can someone please suggest how to check for a parameter and copy from one directory to other within an ant target?
Ant <if/> is part of Ant-Contrib. To use, follow the directions on the Ant-Contrib Tasks installation page:
(1) Copy ant-contrib-0.3.jar to the lib directory of your Ant
installation. If you want to use one of the tasks in your own project,
add the lines
<taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
to your build file.
(2) Keep ant-contrib-0.3.jar in a separate location. You now have to
tell Ant explicitly where to find it (say in /usr/share/java/lib):
<taskdef resource="net/sf/antcontrib/antcontrib.properties">
<classpath>
<pathelement location="/usr/share/java/lib/ant-contrib-0.3.jar"/>
</classpath>
</taskdef>
Hi i'm creating an application in javafx 2.2 and while compiling a native bundle (EXE) I can see that in the Runtime I miss a library I need.
MyApp\runtime\jre\lib\ext\sunjce_provider.jar
I try adding it like this in my build.xml
<fx:deploy width="${javafx.run.width}" height="${javafx.run.height}"
nativebundles="exe"
outdir="${basedir}/${dist.dir}" outfile="${application.title}">
<fx:application name="${application.title}" mainClass="${javafx.main.class}"/>
<fx:resources>
...
<fx:fileset dir="${platform.home}/jre/lib/ext" includes="sunjce_provider.jar"
type="data"/>
</fx:resources>
<fx:info title="${application.title}" vendor="${application.vendor}"/>
</fx:deploy>
But that only leaves it at
MyApp\app\sunjce_provider.jar
Is there a way to accomplish this?
Including Application Libraries
This section shows how to include standard jars which your application relies upon.
Sample build.xml snippet from the JavaFX ant task reference, the key line is <fx:fileset dir="dist" includes="lib/*.jar"/>:
<!-- Expect definition of JavaFX ant tasks is already imported -->
<fx:jar destfile="dist/application.jar">
<!-- Details about application -->
<fx:application name="Sample JavaFX application"
mainClass="test.MyApplication"/>
<!-- Define what auxilary resources are needed -->
<fx:resources>
<fx:fileset dir="dist" includes="lib/*.jar"/>
</fx:resources>
<!-- What to include into result jar file?
Everything in the build tree -->
<fileset dir="build/classes"/>
<!-- Customize jar manifest (optional) -->
<manifest>
<attribute name="Implementation-Vendor" value="Samples Team"/>
<attribute name="Implementation-Version" value="1.0"/>
</manifest>
</fx:jar>
Modifying the JRE components
This section shows you how to customize the the Java runtime components that are bundled with your application.
See the Java Deployment blog on including the sun jce provider in native packaging (noted in question: sunjce_provider.jar in jre for standalone javafx application).
Relevant sections (copy and pasted from the blog entry) are:
If you are using packaging tools to produce an installable package there could be a need to tweak the application image before it is wrapped into the installer. Why? For example you may want to sign the application, so it does not appear to be untrusted to the OS (for example to please Mac OS X Gatekeeper).
Also by default a self-contained application does not contain full copy of Java Runtime. We only include set of mandatory components. Part of the reason why this approach was taken is that we want to reduce the package size. However, there are situations where your application may depend on these optional components and in that case you will need a way to add them to the private runtime. For example https connections will not work if jre/lib/ext/sunjce_provider.jar is missing.
Currently this can be achieved by providing a custom config script that is executed after application image is populated. Like in the example above with the icon, you need to enable verbose output to find the name of the script file and then drop it to the location where packaging tools will find it. Note that scripting language is platform specific too. Currently we only support shell for Mac/Linux and Windows Script on windows.
How do you find out where the application image is located? Currently custom scripts are run in the directory where config files are stored but application image can be accessed using relative platform specific path. You can derive this path from verbose output or by setting environment variable JAVAFX_ANT_DEBUG to true to keep intermediate build artifacts.
Here is sample script (contributed by John Petersen) you can use to add jre/lib/ext/sunjce_provider.jar to the application package of MyApp on the Windows platform. Script using Javascript but you could also use VBScript for Windows scripting.
<?xml version="1.0" ?>
<package>
<job id="postImage">
<script language="JScript">
<![CDATA[
var oFSO = new ActiveXObject("Scripting.FileSystemObject");
var oFolder = oFSO.getFolder(".");
var from = oFolder.path + "\\MyApp\\app\\sunjce_provider.jar";
var to = oFolder.path + "\\MyApp\\runtime\\jre\\lib\\ext";
if (!oFSO.FolderExists(to)) {
oFSO.CreateFolder(to);
}
to += "\\";
oFSO.CopyFile(from, to);
]]>
</script>
</job>
</package>