Deployment: native application bundles

Daniel Zwolenski zonski at googlemail.com
Sat Jun 16 03:03:45 PDT 2012


I like the sound of the pluggable 'bundlers', and agree that having a WiX
free implementation is very low priority if the customisation of WiX is
fairly straight forward.

Thanks for the code snippet - very interesting how you load the DLL and
hook into it. You can ignore my comment about the executable jar, it's not
applicable to the way you are doing things. I imagine native dependencies
will work just fine in your approach.

It all looks good!

If we did want to make this work with the auto-update approach I've
prototyped, the main challenge will be that your bundle assumes the local
version is the only version (as you'd expect it to). It assumes everything
in the app directory should be in the classpath, and the JRE is in the jre
directory. My POC however uses an 'app-profile.xml' to explicitly define
each JAR on the path and the version of the JRE to use.

The reason this app-profile is needed in my POC is that when I download new
versions I can't overwrite the current jars and JRE because they are locked
by the process doing the download - so for some time at least both the new
jars and old jars need to co-exist. My current solution is to append
version numbers to everything, so when I download myapp-2.0.jar, the old
myapp-1.0.jar is still there, same with jre6 and jre7. Then the
app-profile.xml is used to decide which jars and jre are the correct ones
to use and the old ones are ignored. Without an app-profile both the old
1.0 and the 2.0 jar would get loaded.

The app-profile also doubles up as a record of the locally installed
version and is used by the code to determine what needs updating. There
would be plenty of other ways to do this (e.g. query the JVM for its
version and look at the jar names) but the app-profile does make it pretty
simple.

All just stuff to look into as we explore the auto-updating functionality.


Cheers,
Dan



On Sat, Jun 16, 2012 at 4:07 PM, Igor Nekrestyanov <
igor.nekrestyanov at oracle.com> wrote:

>  Hi,
>
>
>  Regarding the MSI installer, using WiX does make it easier but I'm
> wondering if there would be some merit in trying to write our own MSI
> creator using the Windows Installer SDK. I haven't used it myself yet but I
> believe it can be used to create MSI's. This would have the advantage of
> not needing extra software installed, and also would allow us to customise
> closely to what we need specifically for Java installations (e.g. provide
> our own configuration options in whatever syntax or format we want - e.g.
> an 'app-profile.xml'). The disadvantage of course is the extra work, but
> this may be something I could look at in my POC side of it. Something to
> think about anyway.
>
> Basic approach we are using is to adding support for "bundlers" to the
> toolchain. Bundler is something that can produce package out of set of app
> resources, JRE, etc.
> Bundler may or may not have additional requirements (like run only on
> specific platform or require WiX, etc.)
>
> When developer requests to "bundle" app we produce all bundles we can
> generate (by running all applicable bundlers).
>
> JavaFX 2.2 will provide some set of bundlers embedded into packaging tools.
>
> This approach allow to add new bundler or rewrite bundler later on if
> there will be better solution (e.g. WiX-less MSI bundler or cross platform
> deb bundler, etc).
>
> As for WiX-less bundler specifically i think it might be nice to have but
> i do not see it as critical issue right now.
> We are generating WiX config files based on templates and can expose any
> configuration parameters we need in whatever syntax we want.
> Once we understand what is limiting with this approach we can decide on
> how we can get something better.
> Using existing solution that works well for producing MSI allow us to
> focus on JavaFX specific problems and other bundlers.
>
>  Regarding natives, if you are using an executable JAR I don't think this
> will work (i.e. executable JARs don't support native included in them),
> unless the developer does the old extract and include on path trick. Better
> that the natives just get bundled into the installation directory and not
> into the jar, I reckon. It's a bit of a messy area (especially for
> auto-updates) so probably worth making sure we're covered in this area
> fairly early on.
>
> I think it do not understand the problem.
> In my model i assume that application image is something you can run using
> java.exe like
>     cd app-image/
>     java -cp main.jar main.class
> (where app image is your dist of build folder).
>
> When you are running app from your IDE, debugger or command line it knows
> how to load native resources.
> I expect same copy of app-image to be kept under app/ folder in the
> installed image.
>
> Anyway, let me try to craft an example and we will see.
>
>
>
>  Regarding the launching of the process, the way I do it also seems to
> give it the process the name of the app the proper name (and not
> 'java.exe'), which is a pleasant surprise. Do you use the same sort of code
> as follows?
>
> My windows launcher is fairly simple now. Here is relevant part:
>
>
>      // Dynamically load the JVM
>     HMODULE jvmLibHandle = LoadLibrary(jvmPath);
>     if (jvmLibHandle == NULL) {
>         DWORD dwErr = GetLastError();
>         MessageBox(0, _T("Error loading jvm.dll"), jvmPath, MB_ICONERROR |
> MB_OK);
>         return FALSE;
>     }
>
>     //convert argument to ASCII string as this is what CreateJVM needs
>     wcstombs_s(&outlen, jarASCII, (size_t) wcslen(jar) + 1, jar, (size_t)
> wcslen(jar) + 1);
>     strcpy_s(classpath, MAX_PATH*2, "-Djava.class.path=");
>     strcat_s(classpath, MAX_PATH, jarASCII);
>
>     // Set up the VM init args
>     jvmArgs.version = JNI_VERSION_1_2;
>
>     //TODO: add support for custom JVM parameters
>     options[0].optionString = classpath;
>     jvmArgs.version = 0x00010002;
>     jvmArgs.options = options;
>     jvmArgs.nOptions = 1;
>     jvmArgs.ignoreUnrecognized = TRUE;
>
>     // Create the JVM
>     // NB: need to use ASCII string as UNICODE is not supported
>     createProc = (JVM_CREATE) GetProcAddress(jvmLibHandle,
> "JNI_CreateJavaVM");
>     if (createProc == NULL) {
>         MessageBox(0, _T("Failed to locate JNI_CreateJavaVM"), jvmPath,
> MB_ICONERROR | MB_OK);
>         return FALSE;
>     }
>
>     if ((*createProc)(&jvm, &env, &jvmArgs) < 0) {
>         // Should not happen
>         // FIXME: report localized error
>         return FALSE;
>     }
>
>     cls = env->FindClass("com/javafx/main/Main");
>     if (cls != NULL) {
>         mid = env->GetStaticMethodID(cls, "main",
>             "([Ljava/lang/String;)V");
>          if (mid != NULL) {
>             jclass stringClass = env->FindClass("java/lang/String");
>             jobjectArray args = env->NewObjectArray(0, stringClass, NULL);
>             env->CallStaticVoidMethod(cls, mid, args);
>         } else {
>             MessageBox(0, _T("no main method"), _T("Expected to find
> com.javafx.main.Main.main()"), MB_ICONERROR | MB_OK);
>         }
>     } else {
>         MessageBox(0, _T("no main class"), _T("Expected to find
> com.javafx.main.Main"), MB_ICONERROR | MB_OK);
>     }
>
>     if (env->ExceptionOccurred()) {
>         MessageBox(0, _T("Failed due to exception."), _T("Exception thrown
> from com.javafx.main.Main.main()"), MB_ICONERROR | MB_OK);
>         env->ExceptionDescribe();
>     }
>
>
>  -igor
>
>  I'd be keen to keep what I do in line with what you are doing where
> possible.
>
>
>
>
> On Sat, Jun 16, 2012 at 4:59 AM, Igor Nekrestyanov <
> igor.nekrestyanov at oracle.com> wrote:
>
>>  hi, thanks for all questions.
>>
>> Please keep them coming (bugs and suggestions are very welcome too!),
>>
>>
>>  The Ensemble MSI install worked for me on Windows 7 no problems. I
>> haven't tried building my own app as yet though.
>>
>>  It installed into 'C:\Users\zonski\AppData\Local\Ensemble2'. Installing
>> into Program Files is probably more correct on windows. Is this 'appdata'
>> the intended final location, or is this just for getting it all running for
>> now?
>>
>>  Original goal was to be able to install without requiring admin
>> permissions.
>> Both MSI and EXE installers are currently build to do this.
>>
>> It is possible to customize install location and make it system wide by
>> tweaking WiX/Inno Setup template files.
>> Clearly we want to expose better APIs for customization but it is not
>> clear what are importnat config parameters and how to expose them
>> in more or less cross platform way, hence we decided that for 2u2 we will
>> provide an easy way to build basic package and do minimal customization
>> as well as (very) advanced way for advanced users.
>>
>> Based on feedback we will figure out how to expand built-in configuration
>> APIs for future releases.
>>
>> I am planning to post more about package customization options and other
>> tricks&tips but i am amateur blogger and slow typer, so it will take me few
>> days :)
>>
>> Perhaps we should reconsider and produce EXE to be user level
>> installation and MSI to be system level by default.
>> I believe it is also possible to pass parameters to msiexec to overwrite
>> some of MSI settings (end this is not unusual in the enterprise
>> deployments).
>> However, i had not tried if it is possible to install this MSI system
>> wide (and i am not sure if my MSI expertise is deep enough to craft MSI
>> that can do both,
>> suggestions are very welcome).
>>
>>
>>  Is the source code available for this at all?
>>
>>  Sorry, it is part of deploy/packager module that is not open sourced
>> yet.
>>
>>  If not, I'm very interested in how the 'exe' launcher code looks. Is
>> this code you've written or part of one of the tools you've made use of?
>> I'm particularly interested to see how it starts the app - does it just
>> kick off another process on the executable jar via something like 'java
>> -jar ensemble.jar' or does it try to run the Java app within it's own 'exe'
>> process somehow (I'm assuming the later?).
>>
>>  yes, launcher will instantiate JVM in the launcher process.
>> Check out list of processes when sample app is running. There is no
>> java.exe but there is Ensemble.exe
>>
>>
>>  I notice also that the jfx DLLs have been copied straight into the
>> 'jre/bin' directory.
>>
>>  Starting 7u6 JRE/JDK will include JavaFX as part of Java installation.
>> So, nothing special here. It is just runtime image.
>>
>>   Is this how you see all native dependencies playing out, i.e. if my
>> application uses other native libraries how do I package them into the
>> build and where will they be installed to in the extracted directory?
>>
>>  No, i do not think application resources will go into runtime.
>> Application resources will stay in the "app" folder (native libs too).
>>
>> The approach here is to "bundle" app without requiring to rewrite it.
>> During the development cycle your build output should have copy of
>> application you can execute and debug (but it depends on environment, i.e.
>> java+javafx runtime).
>> Bundle is essentially
>>      copy of this application + java runtime  + launcher
>>
>> Having said that i had not tried to craft example with native libraries
>> myself. Will certainly try to do.
>>
>> One more question: when we say we have to build on the native platform to
>> get the correct deployments, does that include 32bit vs 64bit? I'm guessing
>> I could have a 32bit and 64bit JDK installation on the one machine and
>> build a version of my app for each, but correct me if I'm wrong on this.
>>
>>  yes, two installations should do.
>>
>> Currently ant task will try to use RUNNING version of java as source for
>> cobundle.
>> If it is not appropriate (e.g. java 6 that is not javafx cobundle) then
>> it bundled app will not be created.
>>
>> In the future we may add option to specify which JDK to use as import for
>> bundle creation but for now we are taking shortcuts to avoid exposing too
>> much (kind of late in release).
>>
>>  I assume there's no way for a single JDK installation to produce both 32
>> and 64bit versions?
>>
>>  No, as currently JDK installations do not include both 32 and 64 bit
>> bits. After all we are copying them into bundle.
>>
>> -igor
>>
>>  Very, very nice start to this all!
>>
>>  Cheers,
>> Dan
>>
>>
>> On Fri, Jun 15, 2012 at 5:16 PM, Igor Nekrestyanov <
>> igor.nekrestyanov at oracle.com> wrote:
>>
>>> Hi,
>>>
>>> One thing we are adding to JavaFX packaging tools in 2.2 is ability to
>>> produce native application bundles:
>>>
>>> https://blogs.oracle.com/talkingjavadeployment/entry/native_packaging_for_javafx
>>>
>>> We are not seeing this as the only way to deploy JavaFX applications --
>>> webstart, embedded applications
>>> and doubleclickable jars are first class citizens (and it would be great
>>> to explore other options).
>>> But we hope it might be good option for many deployment scenarios.
>>>
>>> Please give it a try and provide feedback (and report bugs of course),
>>>
>>> -igor
>>>
>>
>>
>>
>
>


More information about the openjfx-dev mailing list