• Home
  • Events
  • About
  • Juggling with DLLs, WebStart and Maven

    Juggling with DLLs, WebStart and Maven

    Recently we were asked to implement a Drag & Drop mechanism between Microsoft Outlook and a Java based internet application. This necessitated our Java server having to communicate with COM objects on the client side. How do you do that?

    The good thing is that our application was built using UltraLightClient, so we had java on both the server and on the client side. And after some thinking, the steps seemed pretty clear, even if a tiny bit of juggling would be required. However, the juggle almost turned into a struggle when we encountered some unexpected pitfalls.

    In this blog I will give a quick sketch of our solution and point out some of the traps to be aware of.

    Step 1: Talking COM using JACOB

    In order to communicate with Microsoft programs from Java you need a Java COM Bridge.
    We were using JACOB and it was surprisingly easy to extract Outlook mails into Java objects.

    The idea:
    The following method extracts the selected outlook mails to a directory and returns the list of created files:

    The trap:
    Using the email subject as a file name is practical, but it can contain many weird characters which may not be supported when the files are created. We found out that JACOB has problems creating files containing even characters like “:” and “,”. Furthermore, no exception is thrown, although the file fails to be created completely.

    The solution:
    Replace potentially dangerous characters with something neutral using regular expressions:

    To be on the safe side we were using a whitelist approach. We treat everything as invalid except for characters which are listed after the “^” character.

    Step 2: Shipping a DLL with Webstart

    JACOB can talk to Outlook because it comes with a DLL which has to be present in the classpath. This means we either have to ensure that all our users have this library installed (yikes!) or we ship it together with the application client using Java Webstart.

    The idea:
    We include the DLL in the jar file and sign it with a valid certificate. Then it can be referenced from the JNLP file that launches your web application:

    The trap:
    We were using the optional parameter download=”lazy” to ensure that the library is only downloaded when it is really needed. The result was that it never got loaded at all(!) because we did not specify to which “part” the library belongs. This is another optional parameter which turns mandatory in combination with download=”lazy”.
    Unfortunately this little detail is not too well documented. The only hint found was this one (in german). It took me quite some time to find this critical information.

    The solution:
    Since the jar containing our DLL is really small we chose to use download=”eager” (which is the default anyway) instead of defining “parts” in our JNLP.

    Step 3: Using native lib references with the webstart-maven-plugin

    We already were using Maven as a build system and our client distribution is generated with the webstart-maven-plugin as follows:
    - We use a separate module with packaging type “pom” for the generation of the webstart client. Of course, this module is part of the multi module build for our application.
    - We provide a template for the JNLP file containing a parameter “$dependencies” which will be replaced by a list of the dependencies of the current module
    - At build time the dependencies will be signed and put into a zip file together with the JNLP file.
    - The zip file can be extracted to a java webstart server or, in our case, into a war file that will be deployed on a server.

    The idea:
    Since JACOB is available via Maven Central integration seemed pretty easy. We only have to generate the correct reference to the native library.

    The trap:
    Unfortunately the current version of the webstart-maven-plugin (1.0-alpha-2) does not support native libs (open issue). So we will need a workaround that wraps the jacob.dll into a jar file and generates the nativelib reference in our JNLP.

    The solution:
    Perform the following steps:
    - Change the packaging type for the module from “pom” to “jar”.
    - Configure the pom.xml to copy jacob.dll from the maven repository into the build directory of the module using the maven-dependency-plugin
    - Add the nativelib reference to the velocity template using the build artifact of the current module as a reference.

    Summary:

    After successfully having avoided the traps (okay: by stepping into them and finding a way out again) we got an application with a pretty cool feature integrated seamlessly in our build process. Nice!

    Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
    • DZone
    • Y!GG
    • Webnews
    • Digg
    • del.icio.us
    • DotNetKicks
    • Facebook
    • Google Bookmarks
    • Newsrider
    • Twitter
    • YahooBuzz

    3 Comments »

    1. Shreyas said,

      September 25, 2010 @ 13:44

      Hi Chritoph,
      I am using java webstart plugin and need to use a native library for swt. The dll has been pakaged into a jar file and this jar has been added as a jarResource in the pom file.(This is necessary because the jar needs to be signed with the same signature as all other jars.) Now i have modified the vm template for the jnlp file to include this particular jar file as a native library. The problem is I get two entries in my jnlp file for the same resource. There is a version.xml file that gets generated automatically. Also JnlpDownloadServlet gets invoked. But it gives an error while downloading the jar file. (404) I think this is because there are two entries for the same jar(one as a jar and one as a native lib). What can be done?

    2. christoph said,

      September 30, 2010 @ 17:06

      Just to let everybody know:
      In Shreyas case it was the two entries in the jnlp-file for the jar containing the dll that were causing problems at runtime.
      After some email discussion we decided not to use the $dependencies variable in the velocity template but to list the dependencies explicitely (not using the one with the dll in the jar-section).
      Of course, now every change in the dependency structure has to be adjusted in the template as well but this is does not happen very frequently.
      It is a different story with the project internal dependencies: We are dealing with a multi module build and frequent updates of the version number which we do NOT want to do manually.
      The solution was to parameterize the version number of the project internal dependencies with ${project.version} and replacing the value at build time using the filtering mechanism of the maven-resources-plugin.

    3. Shreyas said,

      October 1, 2010 @ 4:50

      The problem can be solved by using a simple logic in the vm template so as to remove the entry for the dll jar resource. The dependencies come to the vm script as a string and what we can do is
      #set($dependencies = $dependencies.replaceAll(”,”) )
      This would replace the dependencywith an empty string thus removing duplicates.

      One other solution possible here is to use your own jnlp file rather than the one created by webstart plugin. This would have to be used with the maven resource plugin to replace the version numbers in the jnlp file with the current build versions.

      Another alternative is to override the JnlpDownloadServlet to add features to download native dlls from the server and putit to the necessary locations on the client box(eg . system32). This would no longer require the dll jars to be mentioned in the jnlp file.

      Thanks Chris for your help.

    RSS feed for comments on this post · TrackBack URI

    Leave a Comment


    four − 2 =

    css.php