maven-sbs-archetype

The WAR overlay archetype is generally used in a Jive SBS customized implementation when plugins will not suffice. The general idea is that changes within this project are compressed into a WAR, along with the core SBS code, to create a custom SBS instance. While a plugin is the preferred method of customizing your SBS instance, in extreme cases an overlay is acceptable.

maven-sbs-archetype structure

In addition to the standard Maven src folder, the archetype contains a single sub-project, web. The root project's structure contains mainly test resources that allow the local instance to run properly, while the web project houses the customized pieces of the project.



src/test/resources/jiveHome

This is the jiveHome directory that is used by default by the overlay instance.  When the project is built at the root level, the jiveHome directory is copied directly to the root target folder, replacing whatever was there before.  Because of this, save for your initial build,it's probably best not to do your builds from the root level, but at the individual sub-project levels instead.  The initial contents of the folder consists only of:

  • jive_startup.xml: Contains server startup settings, such as database and log info. The initial database name listed is directly affected by the name of the project being generated with the archetype.
  • jive.license: A standard development license. Non-expiring, including all optional modules (except Insights), and limited to 15 users.

web/src/main/etc

Commonly referred to the ETC Escape Hatch, the etc folder is where any Spring XML files are placed.  Jive SBS loads these XML files last when initializing the Spring application context, so any beans defined therein takes precedence over any defined within the core SBS Spring XML files. 

This gives developers the ability to override any Spring beans defined within SBS, as well as add new ones, as needed.  When the web project is built, this directory's contents are copied to the root target/jiveHome/etc.  Although only one file, spring-etc.xml, is included by default, multiple Spring XML files can be included in this directory, if the developer wishes to ruther compartmentalize any custom Spring beans.

web/src/main/java

This is where your custom Java classes will live.  The package structure used here is up to the developer, and should reflect the current project.  However, if an overlay of a core SBS class is needed, the developer needs to create the exact package structure in which the class to be overlaid lives, and the core Java class copied and modified as needed. 

At build time, the core Jive SBS WAR file is exploded, and the contents of the web/src/main/java folder are copied to the exploded WAR's WEB-INF/classes directory, and thusly take precedence over any classes defined in JAR files contained within the WAR's lib directory.  A placeholder class, App.java, is included here by default, but can be deleted when development work starts.

web/src/main/keys

Any public/private encryption key certifications needed by the customization go here.  At build time, contents of this folder are copied to the root target/jiveHome/keys directory to make them available to the development instance.

web/src/main/overlay

Certain overlaid resources cannot just be placed within the WAR's WEB-INF/classes directory for the customization to take effect.  Resources like Javascript files and Widget properties files need to actually replace the original artifacts in the SBS JAR file, and placed back into the WAR.  By default, this is disabled in the web pom.xml for build performance reasons, but can be enabled by uncommenting the package-sbs-plugin execution element in the maven-antrun-plugin section in the pom.

web/src/main/overlay/beans

Overlaid widget properties files are placed here.  Generally, this is needed when adding, removing, or modifying the configurable properties available within a core SBS widget.

web/src/main/overlay/resources/scripts

Any overlaid Javascript resources lives here.  In previous versions of the archetype, overlaid Javascript files needed to be accompanied by a compressed version of the file, but now that processing is done automatically by the build.

web/src/main/resources-filtered

The contents of this folder are filtered at build time, and the parameterized sections of the files contained within are populated with values, such as build number, project name, etc.  The version.properties file is accessed by the web/src/main/webapp/customer_version.jsp to provide information about the build number for a deployed instance.

web/src/main/themes

This is where custom themes go.  The provided theme.xml file is initially populated with a theme name reflecting the name of the project.  This file should be copied into the theme's main folder (web/src/main/theme/mytheme) in order to be visible to the app.  It is merely placed in this folder as a placeholder.

web/src/main/webapp

The webapp folder contains artifact that are to be placed within the exploded WAR file directory.  The archetype provides the customer_version.jsp and a WEB-INF folder to house WAR customizations.

web/src/main/webapp/WEB-INF/classes

A series of files meant to provide a custom configuration to an SBS overlay instance go here.  Specifically:

  • jive_custom_i18n_en.properties: Override existing resource bundle values, and add new mappings here.  This file is created by default.  Should the project require other languages, the developer needs to create the appropriate file variations (such as jive_custom_i18n_es.properties).
  • struts-community-custom.xml: Override core Struts actions here.  New actions can be added, as well.
  • ui-components-custom.xml: Additions, deletions of certain UI components are done here.
  • upgrade-custom.xml: Custom upgrade tasks are defined here. 

web/src/main/webapp/WEB-INF/classes/template

Add your custom FreeMarker templates here.  Generally, if your change is look and feel-related, it goes in a theme.  However, if the change needs to exist outside the context of a theme, such as in a major page structure/logic change, it needs to go here, in the same directory structure as the FTL being overlaid.  Any overlaid FreeMarker templates defined here take precedence over any matching files within the core WAR file.

maven-sbs-archetype profiles

The following section describes the various profiles that exist within the web project's POM. 

Profiles allow for different configurations to be used during a build by specifying the profile when the build is run.  In the case of the overlay project, two profiles are used by default:

  • int: Integration-testing profile. Allows for running all of the integration tests for the project, but more commonly for running the project inside of a local Tomcat instance via Cargo.
  • dev: Largely the same as the int profile, but adds the ability to run the project in an environment a bit more conducive to the iterations associated with development.

Profile: int

The int profile contains two plugins:

  • cargo-maven2-plugin: Discussed in detail below
  • selenium-maven-plugin:  Runs the Selenium integration test suite
  • maven-surefire-plugin:  Specifies that only Selenium integration tests are to be run

The cargo-maven2-plugin allows you to deploy the app to Tomcat for the purpose of running integration tests against the instance, and also to allow for manual use of the app, depending how it is run.

There are several ways to run Cargo:

Command Comments
mvn -P int integration-test Runs the integration tests inside of Cargo and then exits.  Maven runs through all of the other dependent lifecycle phases before running the tests (compile, package, test, and others).  You would use this if you wanted to only run the automated integration tests.
mvn -Dcargo.wait=true -P int integration-test Runs the app within Cargo, after running through dependent Maven lifecycle phases.  The presence of the cargo.wait system property tells Maven to keep the Tomcat instance up and to wait for either user input, or for the instance to be shut down manually.  Note that running this way causes the custom WAR to be rebuilt before the app is deployed.
mvn -Dcargo.wait=true -P int cargo:start Runs the app within Cargo, but does not run through any dependent Maven lifecycle phases.  Rather, it deploys the existing custom WAR to the Tomcat instance, and waits for user input or a manual shutdown.  This option is recommended for plugin development when a new WAR is not required to observe changes in a local instance.

The cargo-maven2-plugin is defined in the POM as follows:

<profiles>
    <profile>
        <id>int</id>
        <build>
            <plugins>
                <!-- Cargo is our main method of running and testing/debugging SBS.  This is the main configuration area. -->
          <!-- Here is the config reference:  http://cargo.codehaus.org/Maven2+Plugin+Reference+Guide    -->
                <plugin>
                    <groupId>org.codehaus.cargo</groupId>
                    <artifactId>cargo-maven2-plugin</artifactId>
                    <version>1.0</version>
                    <configuration>
                  <!-- Feed them this value; Decides if Cargo should wait after the container is started or not -->
                        <wait>${cargo.wait}</wait>
                        <container>
                            <containerId>tomcat6x</containerId>
                            <home>${tomcat6.home}</home>
                            <systemProperties>
                                <jive.instance.home>\${basedir}/../target/jiveHome</jive.instance.home>
                                <jive.ws.disabled>true</jive.ws.disabled>
                                <jive.devMode>true</jive.devMode>
                                <themes.directory>\${basedir}/src/main/themes</themes.directory>
                                <!-- <pluginDirs>\${basedir}/../myplugin/src/main/plugin</pluginDirs> -->
                            </systemProperties>
                            <dependencies>
                       <!-- Throw in our most common jdbc connectors; add yours here if it's missing -->
                                <dependency>
                                    <groupId>mysql</groupId>
                                    <artifactId>mysql-connector-java</artifactId>
                                    <type>jar</type>
                                </dependency>
                                <dependency>
                                    <groupId>postgresql</groupId>
                                    <artifactId>postgresql</artifactId>
                                </dependency>
                                <dependency>
                                    <groupId>javax.servlet</groupId>
                                    <artifactId>servlet-api</artifactId>
                                    <type>jar</type>
                                </dependency>
                            </dependencies>
                        </container>
                        <configuration>
                            <home>target/tomcat6x</home>
                            <properties>
                                <cargo.jvmargs>-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n -Xms512m -Xmx1024m -XX:MaxPermSize=256m -XX:+UseParNewGC -XX:+UseConcMarkSweepGC</cargo.jvmargs>
                            </properties>
                            <deployables>
                                <deployable>
                                    <location>target/${customer.name}-${customer.version}-sbs-${sbs.version}.war</location>
                                    <pingURL>http://localhost:8080/jive</pingURL>
                                    <properties>
                                        <context>jive</context>
                                    </properties>
                                </deployable>
                            </deployables>
                        </configuration>
                    </configuration>
                    <executions>
                        <execution>
                            <id>start-container</id>
                            <phase>pre-integration-test</phase>
                            <goals>
                                <goal>start</goal>
                            </goals>
                        </execution>
                        <execution>
                            <id>stop-container</id>
                            <phase>post-integration-test</phase>
                            <goals>
                                <goal>stop</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>

The configuration element allows for the specification of system properties, deployables, customization of the JVM args, and more.  Each item is discussed below.

<wait>${cargo.wait}</wait>

The value for the wait property is passed through from the command line, and determines whether Cargo will remain up, waiting for user interaction.

<container>
    <containerId>tomcat6x</containerId>
    <home>${tomcat6.home}</home>
    <systemProperties>
        <jive.instance.home>\${basedir}/../target/jiveHome</jive.instance.home>
        <jive.ws.disabled>true</jive.ws.disabled>
        <jive.devMode>true</jive.devMode>
        <themes.directory>\${basedir}/src/main/themes</themes.directory>
        <!-- <pluginDirs>\${basedir}/../myplugin/target/myplugin</pluginDirs> -->
    </systemProperties>
    <dependencies>
        <!-- Throw in our most common jdbc connectors; add yours here if it's missing -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <type>jar</type>
        </dependency>
        <dependency>
            <groupId>postgresql</groupId>
            <artifactId>postgresql</artifactId>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <type>jar</type>
        </dependency>
    </dependencies>
</container>

The container element allows for the configuration of how the Tomcat instance is run.  The home element specifies where the Tomcat instance to be used is located, the value of which should be specified in your Maven settings.xml file.

JVM system properties are specified in the systemProperties element.  The default values are as follows:

System property Value Comments
jive.instance.home ${basedir}/../target/jiveHome This points the SBS instance to the jiveHome directory deployed when the root project is built.
jive.ws.disabled true Disables web services, which makes startup much faster.
jive.devMode true Allows for running SBS in dev mode, which allows for the use of pluginDirs, themes.directory, and disables FTL cacheing.
themes.directory ${basedir}/src/main/themes Specifies that the themes directory used by the app will be the those in the src/main/themes directory.  This allows for changes to the themes to be made and observed on the fly, without rebuilding or restarting.
pluginDirs none Specifes a comma-delimited list of plugins to run, each being represented by a directory containing the contents of the exploded plugin JAR file.  This allows the plugin to be installed in the SBS instance without actually saving it to the database and having to restart.

The dependencies element references upstream dependencies defined within the POM that are needed to properly run the tomcat instance.

    <configuration>
        <home>target/tomcat6x</home>
        <properties>
            <cargo.jvmargs>-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n -Xms512m -Xmx1024m -XX:MaxPermSize=256m -XX:+UseParNewGC -XX:+UseConcMarkSweepGC</cargo.jvmargs>
        </properties>
        <deployables>
            <deployable>
                <location>target/${customer.name}-${customer.version}-sbs-${sbs.version}.war</location>
                <pingURL>http://localhost:8080/jive</pingURL>
                <properties>
                    <context>jive</context>
                </properties>
            </deployable>
        </deployables>
    </configuration>
</configuration>

The configuration element defines various Cargo properties, including how to start the JVM, and where the artifacts to be deployed reside.  The home element specifies where the WAR being deployed should be copied to and exploded.  Running SBS is very memory intensive and requires that additional memory be allocated to the stack, which is done using the cargo.jvmargs property.  The webapps to run are defined in the deployables element, each supplying the location of the war to be deployed, as well as the context under which the deployable is to be run.  By default, only one deployable is defined: the WAR created during the build, which runs under the jive context (http://localhost:8080/jive).

Profile: dev

The dev profile, like the int profile, provides for the running of the customized SBS instance locally, via Tomcat and Cargo, but without the notion of integration testing being the purpose. 

The plugins offered by the profile are:

  • cargo-maven2-plugin
  • javarebel-maven-plugin

The cargo-maven2-plugin functions largely the same as in the int profile, but with a few more options to better facilitate the use of Java Rebel.  For example, the following system properties are specified in the systemProperties element:

System property Default value Comments
docverse.enabled false Disables the DocVerse module, which causes problems with JavaRebel
rebel.struts2-plugin true Enables Rebel monitoring of Struts configuration changes

The JavaRebel plugin is commented out by default, since it requires a license to run.  Java Rebel allows for the monitoring of class directories so that changes can be hot-deployed to a running instance without a restart.

<!--<plugin>
    <groupId>org.zeroturnaround</groupId>
    <artifactId>javarebel-maven-plugin</artifactId>
    <executions>
        <execution>
            <id>generate-rebel-xml</id>
            <phase>process-resources</phase>
            <goals>
                <goal>generate</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <classpath>
            <fallback>default</fallback>
            <resources>
                <resource>
                    <directory>\${basedir}/../myplugin/target/classes</directory>
                </resource>
                <resource>
                    <jarset>\${basedir}/../myplugin/target/dependency</jarset>
                </resource>
            </resources>
        </classpath>
        <war>
            <path>\${basedir}/target/${customer.name}-${customer.version}-sbs-${sbs.version}</path>
        </war>
    </configuration>
</plugin> -->

The custom WAR file is specified by default.  To target additional directories, such as plugins, an entry for the plugin's classes directory is needed in the resources element, like shown in the listing above.  This will allow for changes to the plugin's code to be monitored and loaded without having to rebuild the plugin and restart the server.