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>
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 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'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
We run the application from the attached JNLP. On the Java console, we have output the system properties with D. The properties from our JNLP files are not set any more. This is the first Java version that we get this sort of problems with. Everything was working fine up to and including 7 Update 40.
We have all the jars signed but there are no security attributes in their manifests.
<?xml version="1.0" encoding="UTF-8"?>
<jnlp spec="1.0+" codebase="http://10.0.10.230/webstart/app" href="desktop.jnlp">
<information>
<title>MyApp Desktop</title>
<vendor>MyApp GmbH</vendor>
<homepage href="http://www.myres-edv.de"/>
<description>MyApp Desktop</description>
<offline-allowed/>
</information>
<security>
<all-permissions/>
</security>
<resources>
<j2se version="1.5+" initial-heap-size="512M" max-heap-size="1024M" javaws-vm-args="-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8200"/>
<property name="org.omg.CORBA.ORBInitialHost" value="10.0.10.230"/>
<property name="org.omg.CORBA.ORBServerHost" value="10.0.10.230" />
<property name="sun.net.spi.nameservice.provider.1" value="dns,sun" />
<property name="MyApp.baktswritedos" value="true"/>
<property name="MyApp.nocomm" value="true"/>
<property name="MyApp.la.erfassungdos" value="true"/>
<property name="com.sun.corba.ee.transport.ORBTCPConnectTimeouts" value="500:30000:40:30000" />
<property name="deployment.trace.level" value="all" />
<jar href="myresjar/ejb/myres/myres_ejb_client.jar" main="true" download="eager"/>
<jar href="myresjar/ejb/myres/myres_ejb.jar" download="eager"/>
<extension name="jars" href="commonejbjars.jnlp"/>
<extension name="jars" href="jr.jnlp"/>
<extension name="jars" href="commonjars.jnlp"/>
<extension name="jars" href="commonjh.jnlp"/>
<nativelib href="myresjar/ejb/myres/myres_dll.jar"/>
</resources>
<resources os="Windows">
<nativelib href="myresjar/myres/native-dlls.jar" download="eager"/>
</resources>
<application-desc main-class="de.myapp.gui.desktop.mainframe.DesktopMainFrame">
<argument>-serverIP=10.0.0.230</argument>
<argument>-initNewDayAction=true</argument>
</application-desc>
</jnlp>
We experienced the same Problem with Java 7 Update 45 (1.7.0_45). The JNLP Spec gave a hint for a work-around:
Properties set in the jnlp file will normally be set by Java Web Start after the VM is started but before the application is invoked. Some properties are considered "secure" properties and can be passed as -Dkey=value arguments on the java invocation command line.
The following properties, as well as properties beginning with either "javaws." or "jnlp.", are considered "secure" and will be passed to the VM in this way:
...
While "insecure" properties stopped working, we realized that "secure" properties would still be set correctly.
Maybe the mechanism that sets properties after the VM is started but before the application is invoked, got broken with this Java update, or maybe this was an intentional but undocumented change.
The work-around now depends on the type of system properties:
For system properties that affect Java behavior or libraries, we changed our code to call System.setProperty() at the application start instead of setting them in the JNLP.
For properties that we use to configure the application from the JNLP file, we added the jnlp. prefix so that they are passed correctly again.
<property name="myconfig" value="DE" />
to
<property name="jnlp.myconfig" value="DE" />
Edit: According to OpenJDK Bug JDK-8023821, the change was intentional:
Starting from 7u45 launch descriptor (JNLP file) need to be signed in order to set insecure system properties. So it is expected behaviour in 7u45...
(from a comment)
Instructions for signing a JNLP.
We got bit badly by this same issue. We ended up going the route of including the JNLP file in the signed jar, but that presented some tricky build issues for us, because we had previously built one set of JARS and used multiple JNLP files to support different environments (QA, Production, Demo, etc), passing the environment details through to the app via a system property. We did try to make use of a JNLP template file as discussed here, http://docs.oracle.com/javase/7/docs/technotes/guides/jweb/security/signedJNLP.html, but we kept getting errors related to verifying the JNLP file and gave up due to time constraints. It's possible we were just doing something wrong, but the error messages did not make it at all clear what part of the JNLP file didn't match the template. Additionally, there is this somewhat unhelpful note in the link above that says: "Elements or attributes that may compromise security will be locked out from this feature." I could find no documented examples of such elements or attributes.
Had the same problem and solved it by signing the jnlp file. Your main jar should contain a copy of the jnlp file renamed as APPLICATION.JNLP and placed under JNLP-INF folder.(the name of the folder and jnlp file must be uppercase)
I set as:
<jnlp>
...
<application-desc main-class="Main">
<argument>param1=value1</argument>
</application-desc>
</jnlp>
Ps. Just be aware that passing values using tag you are passing application parameters and not JVM parameter. Your application should catch this parameter in your method main(String args[])
Just spent 2 days trying to fix this problem, trying to sign jars and other files...and then I found the solution which seems to be very simple and is working fine:
I *put a jndi.properties-file with the following content in my JRE-home-director*y (jre7/lib):
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=jnp://localhost:1099
I had this problem when updating from Java 1.6 to Java 1.7(51)...
My application needs to run both from the command-line and a web app. The way I've chosen to implement this is to have the entire application in a single jar file (i.e. my application-specific classes coexist with the classes from the jars my app uses). This makes the command-line use case simple, as the user only has to type java -jar JARNAME. For the web app use case, I simply include the jar in WEB-INF/lib and all is well, almost.
The problem I have is that a few of the jars I'm slurping into the single jar define providers in META-INF/services for the same service, so the single jar ends up with multiple entries in META-INF/services with the same name. (For the curious, these are Jersey jars, and the services are javax.ws.rs.ext.MessageBodyReader and javax.ws.rs.ext.MessageBodyWriter.) So I'm trying to prevent the MessageBody* service files from being slurped into my jar file. Here's how I'm trying (and failing) to accomplish that:
<jar destfile="build/jammies.jar">
<archives>
<zips>
<restrict>
<fileset dir="lib">
<include name="*.jar"/>
<exclude name="servlet-api.jar"/>
</fileset>
<rsel:not>
<rsel:name regex="META-INF/services/javax.ws.rs.ext.*"/>
</rsel:not>
</restrict>
</zips>
</archives>
</jar>
I do have the rsel namespace defined at the top of build.xml.
<project basedir="." default="compile"
xmlns:rsel="antlib:org.apache.tools.ant.types.resources.selectors">
So I don't understand why the restrict task isn't filtering out those particular service provider files.
I think its because the regex starts matching the filename strings from the start however no file begins with META-INF, they would begin with ${basedir}/WEB-INF/lib/META-INF...