Wiki

Clone wiki

mapacho / Home

mapacho.jpg

Mapacho is an open source Java Web Start framework for packaging, deploying, launching and upgrading Desktop Java Applications.

Mapacho is based on Maven, the JNLP and Servlet APIs, a number of jar compression tools and JavaFX to display a preloader / launcher.

The intention behind Mapacho is to allow users to deploy and launch the application with whatever version of Java installed on the users desktop. This is achieve reducing the Java Web Start execution code to a minimal jar with as simple as possible logic to minimize the chances of some JRE update breaking the application. Once the mapacho launcher is executed over Java Web Start, the application can run under the specified JRE or JDK in a "naked" environment (without the JWS layer, just like when the application Runs on the IDE).

Developers can define the version and architecture of the JRE to be used by the application (e.g. 8u60. x64) and any JVM flags supported by the JVM. The specified JRE is automatically downloaded from the server containing the client application. The server side component of Mapacho (The MapachoServlet) will download the requested JRE from the Oracle website, cache it on the application server and then stream it to the client.

Mapacho uses the jardiff protocol to only transmit the portions of JARs that have changed from one version to another and uses pack200 and gz compression for jars as well as for jardiffs.

Jar versioning is managed using Maven APIs.

Framework benefits

Build / Packaging

  • Faster build / packaging. Applications with 100 jars get packaged for JWS deployment in about 2 seconds. This is achived by:

  • Removing pack, unpack, repack and gz compression tasks from the build process

  • Reducing jar sign time by signing one 1Mb jar only per deployment descriptor (jnlp file) and caching it if no change has been detected.

  • Multi threaded packaging (resolving dependencies, packaging).

  • Correct handling of -SNAPSHOT dependencies (Using Maven Apis and appending unique identifier to -SNAPSHOT dependencies in the local maven repo).

  • Multiple JNLP files can be generated via maven plugin using a single JNLP template and descriptor inheritance so one can define some base settings for all JNLPs on a base configuration and then have the specifics of each JNLP on a maven configuration element.

  • Deferring JRE packaging to the application server's runtime

  • Jar signing with timestamping so the application runs after the code signing certificate has expired.

  • Packages the desktop application in a .war module with a built in Servlet to serve application's artifacts

Deployment

  • Improved deployment performance by

  • Using jar-diff, pack200 and .gz compression

  • Caching compressed jar and jar-diff artifacts on the application server's temp dir

  • Users download the specified JRE from the application server itself.

  • If the users request a JRE that is not present on the Application server's hard drive, it will be streamed from the Oracle website to the client PC and writing a copy of it to the server's hard drive for further requests.

  • Artifact and JRE compression during the streaming process so decompression times so users only wait for network download time without decompression overheads.

  • Allows users to keep their java plugin up to date without compromising the stability of the application. This is achieved by running minimal code on the java web start container and hence reducing the chances of issues caused by JRE upgrades or JWS container bugs or behavior differences with the plain JVM runtime (what developers normally use when developing).

Application startup

  • Faster startup times as it reduces jar signature verification and class loading times in general.

  • Reduces the chances of startup issues caused by JRE upgrades by running only one minimal jar with as simple as possible logic on the web start container

  • A JavaFX application preloader and launcher with the following characteristics:

  • Preloader runs on the JWS container and the application on a pure JVM communicating with the preloader over TCP.

  • Multiple progress bars indicating jar and JRE download progressess

  • Preloader API to allow the application to send messages to the preloader over localhost TCP connection.

  • Animated at any time of the application's startup process (even during the start() method of a JavaFX application or while the application's JavaFX thread is loading the initial Scene.

  • Displays custom messages and progress as the application starts up

  • Hide / show preloader with a fade animation as indicated by the application

  • Preloader is 300 Kb in size and uses a single jar so it downloads and displays quickly

Usage Samples

Simple JavaFX application signed with a code signing certificate stored in the company's private maven repository, Java 8 update 60, any architecture, 1gb heap space

#!xml

           <plugin>
                <groupId>uno.anahata</groupId>
                <artifactId>mapacho-plugin</artifactId>
                <version>${project.version}</version>
                <executions>
                    <execution>                        
                        <goals>                            
                            <goal>mapacho</goal>
                        </goals>
                    </execution>
                </executions>

                <configuration>
                    <jnlpFiles>
                        <jnlpFile>
                            <displayName>Mapacho Test App</displayName>
                            <metaInfApplicationName>Mapacho Test App</metaInfApplicationName>
                            <splash>/images/splash-screen.jpg</splash>
                            <jre>
                                <ver>8u60</ver>
                                <build>27</build>
                                <arch></arch>
                            </jre>
                            <jvmArgs>-Xmx1g</jvmArgs>
                            <templateFilename>mapacho.vm</templateFilename>
                            <mainClass>uno.anahata.mapacho.test.app.MapachoTestApplication</mainClass>
                            <jarResources>
                                <jarResource>
                                    <groupId>${project.groupId}</groupId>
                                    <artifactId>mapacho-test-app</artifactId>                                            
                                    <version>${project.version}</version>                                    
                                </jarResource>
                            </jarResources>
                        </jnlpFile>
                    </jnlpFiles>

                    <sign>
                        <keystoreResource>
                            <groupId>com.anahata</groupId>
                            <artifactId>anahata-jks</artifactId>
                            <version>09-2016</version>
                            <keystore>anahata.p12</keystore>
                        </keystoreResource>
                        <storetype>pkcs12</storetype>
                        <keypass>IamNotTellingYou</keypass>
                        <storepass>IamNotTellingYouEither</storepass>
                        <alias>anahata</alias>
                        <tsaLocation>http://timestamp.comodoca.com</tsaLocation>                        
                    </sign>
                </configuration>
            </plugin>

Enterprise Applicaiton Producing 9 jnlp files (all using the same Velocity jnlp template), The first one requiring the 32 bit serial/parallel port DLL for Windows so this will ensure the application runs on the 32 bit version of Java 8 update 60

#!xml

            <plugin>
                <groupId>uno.anahata</groupId>
                <artifactId>mapacho-plugin</artifactId>
                <version>${mapacho.version}</version>                       
                <executions>
                    <execution>
                        <phase>process-resources</phase>
                        <goals>
                            <goal>mapacho</goal>
                        </goals>
                    </execution>
                </executions>

                <configuration>
                    <jnlpBase>
                        <splash>/images/splash-screen.jpg</splash>
                        <preloaderClass></preloaderClass>
                        <jre>
                            <ver>8u60</ver>
                            <build>27</build>
                        </jre>
                        <templateFilename>mapacho/mapacho.vm</templateFilename>
                        <jvmArgs>-Xmx1g</jvmArgs>
                        <mainClass>es.magefrigor.client.Main</mainClass>
                        <jarResources>
                            <jarResource>
                                <groupId>es.magefrigor</groupId>
                                <artifactId>magefrigor-app</artifactId>
                                <version>${project.version}</version>
                            </jarResource>
                        </jarResources>
                    </jnlpBase>
                    <jnlpFiles>
                        <jnlpFile>
                            <displayName>Bascula - Magefrigor</displayName>                                    
                            <outputFilename>bascula.jnlp</outputFilename>                                    
                            <arguments>
                                <argument>bascula</argument>
                            </arguments>                                    
                            <jre>
                                <os>windows</os>
                                <arch>x86</arch>
                            </jre>
                            <jarResources>
                                <jarResource>
                                    <groupId>org.rxtx</groupId>
                                    <artifactId>rxtxcomm-win32</artifactId>                                        
                                    <version>1.0</version>
                                    <nativelib>true</nativelib>            
                                    <os>windows</os>                                
                                    <arch>x86</arch>
                                </jarResource>
                            </jarResources>
                        </jnlpFile>

                        <jnlpFile>
                            <displayName>Acceso Distribuidores - Magefrigor</displayName>                                    
                            <outputFilename>casa.jnlp</outputFilename>
                            <arguments>
                                <argument>casa</argument>
                            </arguments>
                        </jnlpFile>                                

                        <jnlpFile>
                            <displayName>Herramienta Administracion - Magefrigor</displayName>                                    
                            <outputFilename>admin.jnlp</outputFilename>
                            <arguments>
                                <argument>admin</argument>
                            </arguments>
                        </jnlpFile>
                        <jnlpFile>
                            <displayName>Agricultura - Magefrigor</displayName>                                    
                            <outputFilename>agricultura.jnlp</outputFilename>
                            <arguments>
                                <argument>agricultura</argument>
                            </arguments>
                        </jnlpFile>
                        <jnlpFile>
                            <displayName>Albaranes - Magefrigor</displayName>                                    
                            <outputFilename>albaranes.jnlp</outputFilename>
                            <arguments>
                                <argument>albaranes</argument>
                            </arguments>
                        </jnlpFile>
                        <jnlpFile>
                            <displayName>Bascula (sin nativelib) - Magefrigor</displayName>                                    
                            <outputFilename>bascula2.jnlp</outputFilename>                                    
                            <arguments>
                                <argument>bascula</argument>
                            </arguments>
                        </jnlpFile>
                        <jnlpFile>
                            <displayName>Entrada - Magefrigor</displayName>                                    
                            <outputFilename>entrada.jnlp</outputFilename>
                            <arguments>
                                <argument>entrada</argument>
                            </arguments>
                        </jnlpFile>

                        <jnlpFile>
                            <displayName>Sala Despiece Admin - Magefrigor</displayName>                                    
                            <outputFilename>sde.jnlp</outputFilename>
                            <arguments>
                                <argument>sde</argument>
                            </arguments>
                        </jnlpFile>

                        <jnlpFile>
                            <displayName>Yam - Magefrigor</displayName>                                    
                            <outputFilename>yam.jnlp</outputFilename>
                            <arguments>
                                <argument>yam</argument>
                            </arguments>
                        </jnlpFile>

                    </jnlpFiles>

                    <sign>                        
                        <keystoreResource>                            
                            <groupId>com.anahata</groupId>
                            <artifactId>anahata-jks</artifactId>
                            <version>09-2016</version>
                            <keystore>anahata.p12</keystore>
                        </keystoreResource>
                        <storetype>pkcs12</storetype>
                        <keypass>GuessWhat</keypass>
                        <storepass>IsTobaccoBad?</storepass>
                        <alias>anahata</alias>
                        <tsaLocation>http://timestamp.comodoca.com</tsaLocation>
                    </sign>
                </configuration>
            </plugin>

Updated