Juggling with DLLs, WebStart and Maven
May 6th, 2010Juggling 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:
[[code]]czoxOTU6XCINCnB1YmxpYyBTdHJpbmcgZ2V0VmFsaWRGaWxlTmFtZShTdHJpbmcgcmF3U3RyaW5nKSB7DQogICAgUGF0dGVybiBpbnZ7WyYqJl19YWxpZENoYXJhY3RlcnMgPSBQYXR0ZXJuLmNvbXBpbGUoXCJbXkEtWmEtejAtOV8ge30rIV1cIik7DQogICAgcmV0dXJuIGludmFsaWRDe1smKiZdfWhhcmFjdGVycy5tYXRjaGVyKHJhd1N0cmluZykucmVwbGFjZUFsbChcIiBcIik7DQp9DQpcIjt7WyYqJl19[[/code]]
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:
[[code]]czoxNjc6XCINClsuLi5dDQogICAgPCEtLSBBdHRlbnRpb246IFRoaXMgZG9lcyBub3Qgd29yayEhISAtLT4NCiAgICA8cmVzb3VyY2V7WyYqJl19cyBvcz1cIldpbmRvd3NcIj4NCiAgICAgICAgPG5hdGl2ZWxpYiBocmVmPVwibXktZGxsLmphclwiIGRvd25sb2FkPVwibGF6eVwiLz4NCiAgIHtbJiomXX0gPC9yZXNvdXJjZXM+DQpbLi4uXQ0KXCI7e1smKiZdfQ==[[/code]]
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.
[[code]]czoxNTE6XCINClsuLi5dDQogICAgPCEtLSBUaGlzIG9uZSBpcyBlYXNpZXIgYW5kIGl0IHdvcmtzISAtLT4NCiAgICA8cmVzb3VyY2V7WyYqJl19cyBvcz1cIldpbmRvd3NcIj4NCiAgICAgICAgPG5hdGl2ZWxpYiBocmVmPVwibXktZGxsLmphclwiLz4NCiAgICA8L3Jlc291cmNlcz4NClt7WyYqJl19Li4uXQ0KXCI7e1smKiZdfQ==[[/code]]
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.
[[code]]czoyNjA6XCINClsuLi5dDQogICAgPHJlc291cmNlcz4NCiAgICAgICAgPGoyc2UgdmVyc2lvbj1cIjEuNStcIiBpbml0aWFsLWhlYXAtc3tbJiomXX1pemU9XCIyNTZNXCIgbWF4LWhlYXAtc2l6ZT1cIjUxMk1cIi8+DQogICAgICAgICRkZXBlbmRlbmNpZXMNCiAgICA8L3Jlc291cmNlcz4NCntbJiomXX0gICAgPHJlc291cmNlcyBvcz1cIldpbmRvd3NcIj4NCiAgICAgICAgPG5hdGl2ZWxpYiBocmVmPVwiJHtwcm9qZWN0LmJ1aWxkLmZpbmFse1smKiZdfU5hbWV9LmphclwiLz4NCiAgICA8L3Jlc291cmNlcz4NClsuLi5dDQpcIjt7WyYqJl19[[/code]]
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!
Posted by christoph


