The Concept
The first step in getting an installer built is to be able to construct what will roughly be the folder structure of your application. Out of trial and error, or maybe out of a Java convention I don’t know about, we ended up with a folder structure we use in every project. This folder structure has been used in building Windows services as well as desktop applications and has worked out pretty well.
Standard Folders
- lib: all jars and dependency jars go here. We don’t uber-jar anything so small patches can be applied later over the network.
- conf: all configuration files. It’s better to have one place the customer has to go to to configure your product. Only configuration files that will never be touched can be included as resources inside jars.
- logs: all log files will be written here. Again, it’s great to have one place the customer has to go to look at logs whether it’s one log file, or several.
Other Folders
- images, sounds, etc.: whatever your application needs to run.
Usually we put lib and conf on the classpath as well as any other folders that contain things we need like images, etc. This means we don’t have to hardcode folder references or anything like that. Everything is loaded as a classpath resource!
The Maven Assembly Plugin
All of our projects inherit from one root pom. This root pom contains a lot of stuff like what tests and reports to run, managed versions of libraries, etc. It also contains our standard build process for installers under a separate profile. All a developer has to do is call
mvn package -Pinstaller
to build the installer. Jenkins also calls the same profile with some extra parameters to get a properly versioned installer.
Assembly Descriptor
Every project that can or should be assembled has an assembly descriptor at a standard location.
${basedir}\src\main\assembly\assembly.xml
It’s up to the project’s developer to add whatever files the project needs to run to this descriptor.
Configuration
The build process also expects some standard configuration stuff to be around. Each configuration file can be filtered to include environment (test vs. production vs. etc.) specific settings. The result is you can build a versioned installer for test as easily as you can for production or your staging environment.
Including the Assembly Plugin
<project>
<profiles>
<id>installer</id>
<properties>
<environment>test</environment> <!-- the default environment to build -->
<installer.manufacturer>Company</installer.manufacturer> <!-- your company, used later in the WiX source files -->
<installer.windows_installer_version>405</installer.windows_installer_version> <!-- the minimum Windows Installer version all our projects require -->
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<filters>
<filter>${basedir}\src\main\assembly\configuration-all.properties</filter> <!-- include some common configuration properties -->
<filter>${basedir}\src\main\assembly\configuration-${environment}.properties</filter> <!-- include the current environment's properties -->
</filters>
<descriptors>
<descriptor>${basedir}\src\main\assembly\assembly.xml</descriptor>
</descriptors>
<appendAssemblyId>false</appendAssemblyId> <!-- don't append the assembly id to the output directory -->
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profiles>
</project>
A Sample Assembly Descriptor
This is a sample assembly descriptor. It’s pretty self explanatory, everything gets copied out to the target directory.
<assembly>
<id>some application</id>
<formats>
<format>dir</format> <!-- we're creating a directory structure -->
</formats>
<files>
<file>
<source>${basedir}\conf\someConfiguration.properties</source>
<outputDirectory>/conf</outputDirectory>
<filtered>true</filtered> <!-- filter it so it has environment configuration stuff -->
</file></pre>
<file>
<source>${basedir}\src\main\bat\start.bat</source> <!-- a batch file to start the application, icons will later point to this -->
<outputDirectory>/</outputDirectory>
<filtered>false</filtered>
</file>
</files>
<fileSets>
<fileSet>
<directory>${basedir}\native\windows\amd64</directory> <!-- some native libraries required to run the app -->
<outputDirectory>/native/windows/amd64</outputDirectory>
<includes>
<include>*.dll</include>
</includes>
</fileSet>
<fileSet>
<directory>${basedir}\native\windows\x86</directory>
<outputDirectory>/native/windows/x86</outputDirectory>
<includes>
<include>*.dll</include>
</includes>
</fileSet>
</fileSets>
<dependencySets>
<dependencySet> <!-- include all the dependencies of the application -->
<outputDirectory>/lib</outputDirectory>
<unpack>false</unpack>
</dependencySet>
</dependencySets>
</assembly>
Next Post
I hope to cover the cool WiX stuff we’ve done in the next post soon! Here’s the next post!
[…] first post about assembling an application is here. Share this:Like this:LikeBe the first to like this […]