Usage

Java Daemon based on Java Service Wrapper

The following shows how to generate start scripts to make an application run as a Linux daemon.

The setup is based on Java Service Wrapper (JSW) version 3.2.3, using the version 3.2.3.

With org.tanukisoftware.wrapper.WrapperSimpleApp

This is the simplest configuration according to JSW documentation, which invokes a main method on start, and kills the VM on stop. Here is an example usage:

<project>
  [...]
  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>appassembler-maven-plugin</artifactId>
        <version>1.10</version>
        <executions>
          <execution>
            <id>generate-jsw-scripts</id>
            <phase>package</phase>
            <goals>
              <goal>generate-daemons</goal>
            </goals>
            <configuration>
              <repositoryLayout>flat</repositoryLayout>
              <includeConfigurationDirectoryInClasspath>true</includeConfigurationDirectoryInClasspath>
              <daemons>
                <daemon>
                  <id>app1</id>
                  <!-- the next line is added by default if you don't have wrapperMainClass's setting -->
                  <wrapperMainClass>org.tanukisoftware.wrapper.WrapperSimpleApp</wrapperMainClass>
                  <mainClass>org.codehaus.mojo.SomeMainClass</mainClass>
                  <commandLineArguments>
                    <commandLineArgument>start</commandLineArgument>
                  </commandLineArguments>
                  <platforms>
                    <platform>jsw</platform>
                  </platforms>
                </daemon>
              </daemons>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

With org.tanukisoftware.wrapper.WrapperStartStopApp

<project>
  [...]
  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>appassembler-maven-plugin</artifactId>
        <version>1.10</version>
        <executions>
          <execution>
            <id>generate-jsw-scripts</id>
            <phase>package</phase>
            <goals>
              <goal>generate-daemons</goal>
            </goals>
            <configuration>
              <repositoryLayout>flat</repositoryLayout>
              <includeConfigurationDirectoryInClasspath>true</includeConfigurationDirectoryInClasspath>
              <daemons>
                <daemon>
                  <id>app1</id>
                  <!-- the next line is added by default if you dont have wrapperMainClass's setting -->
                  <wrapperMainClass>org.tanukisoftware.wrapper.WrapperStartStopApp</wrapperMainClass>
                  <mainClass>org.codehaus.mojo.SomeMainClass</mainClass>
                  <commandLineArguments>
                    <commandLineArgument>fill.your.arguments</commandLineArgument>
                  </commandLineArguments>
                  <platforms>
                    <platform>jsw</platform>
                  </platforms>
                </daemon>
              </daemons>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

With org.tanukisoftware.wrapper.WrapperListener

The below example assumes you have a main class that implements org.tanukisoftware.wrapper.WrapperListener interface.

<project>
  [...]
  <dependencies>
    <dependency>
      <!-- this must match with the actual JSW runtime distribution, the scope must set as provided since this plugin already add wrapper.jar into the classpath -->
      <groupId>tanukisoft</groupId>
      <artifactId>wrapper</artifactId>
      <version>3.2.3</version>
      <scope>provided</scope>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>appassembler-maven-plugin</artifactId>
        <version>1.10</version>
        <executions>
          <execution>
            <id>generate-jsw-scripts</id>
            <phase>package</phase>
            <goals>
              <goal>generate-daemons</goal>
            </goals>
            <configuration>
              <repositoryLayout>flat</repositoryLayout>
              <includeConfigurationDirectoryInClasspath>true</includeConfigurationDirectoryInClasspath>
              <daemons>
                <daemon>
                  <id>app1</id>
                  <wrapperMainClass>org.codehaus.mojo.SomeMainClass</wrapperMainClass>
                  <commandLineArguments>
                    <commandLineArgument>fill.your.arguments</commandLineArgument>
                  </commandLineArguments>
                  <platforms>
                    <platform>jsw</platform>
                  </platforms>
                </daemon>
              </daemons>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

With org.tanukisoftware.wrapper.WrapperJarApp

The below example assumes you are using org.tanukisoftware.wrapper.WrapperJarApp to start your app, and your current project has main class configured via its manifest.

<project>
  [...]
  <dependencies>
    [...]
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>appassembler-maven-plugin</artifactId>
        <version>1.10</version>
        <executions>
          <execution>
            <id>generate-jsw-scripts</id>
            <phase>package</phase>
            <goals>
              <goal>generate-daemons</goal>
            </goals>
            <configuration>
              <repositoryLayout>flat</repositoryLayout>
              <includeConfigurationDirectoryInClasspath>true</includeConfigurationDirectoryInClasspath>
              <daemons>
                <daemon>
                  <id>app1</id>
                  <wrapperMainClass>org.tanukisoftware.wrapper.WrapperJarApp</wrapperMainClass>
                  <platforms>
                    <platform>jsw</platform>
                  </platforms>
                </daemon>
              </daemons>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
</project>

Using the generated scripts

  • All dependencies and the artifact itself are placed in target/generated-resources/appassembler/jsw/app1/lib directory.
  • The JSW bin scripts are placed in the target/generated-resources/appassembler/jsw/app1/bin directory.
  • The JSW configuration file is placed in the target/generated-resources/appassembler/jsw/app1/conf directory.
$ mvn package

$ chmod +x target/generated-resources/appassembler/jsw/app1/bin/app1

$ chmod +x target/generated-resources/appassembler/jsw/app1/bin/wrapper-linux-x86-32

$ target/generated-resources/appassembler/jsw/app1/bin/app1 start

$ ps -ef | grep java
(to check that it is running)

$ target/generated-resources/appassembler/jsw/app1/bin/app1 stop

Add application specific shutdown code, when the WrapperSimpleApp is used

  • The JSW default stop script use the "kill" command. Use a shutdown hook to override this behaviour with application specific shutdown code.

    E.g. add something like the following to your Main method:

    Runtime.getRuntime().addShutdownHook(new Thread(){
        public void run() {
            log.debug("Shutdown hook was invoked. Shutting down App1.");
            App1JmxStopper appJmxStopper = new App1JmxStopper();
            appJmxStopper.stop();
        }
    });