Fork me on GitHub

Ninja standalone

Introduction

Ninja features a standalone mode where you do not need a separate servlet container. The standalone mode enables you to package your application along with a fast, embedded HTTP server (Jetty in that case). There are several options for packaging your application using standalone mode.

Option 1 - Uber/Fat Jar using Assembly Maven Plugin

This allows you to drop that self-executing file to your server run your application with zero external dependencies. Due to Ninja's client-side sessions it becomes really simple to have one reverse proxy in front of many Ninja instances.

In order to do so you have to first of all add ninja-standalone as dependency to your pom.xml:

<dependency>
    <groupId>org.ninjaframework</groupId>
    <artifactId>ninja-standalone</artifactId>
    <version>X.X.X</version>
</dependency>

Don't forget to change packaging value from war to jar.

<packaging>jar</packaging>

Packaging the application is done via the maven shade plugin. Add the following snipplet to your pom.xml.

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-shade-plugin</artifactId>
  <version>2.2</version>
  <configuration>
    <createDependencyReducedPom>true</createDependencyReducedPom>
    <filters>
      <filter>
        <artifact>*:*</artifact>
        <excludes>
          <exclude>META-INF/*.SF</exclude>
          <exclude>META-INF/*.DSA</exclude>
          <exclude>META-INF/*.RSA</exclude>
        </excludes>
      </filter>
    </filters>
  </configuration>
  <executions>
    <execution>
      <phase>package</phase>
      <goals>
        <goal>shade</goal>
      </goals>
      <configuration>
        <transformers>
          <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
          <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
            <mainClass>ninja.standalone.NinjaJetty</mainClass>
          </transformer>
        </transformers>
      </configuration>
    </execution>
  </executions>
</plugin>

Whenever you build your application on the command line this will generate a fat jar inside your target directory. Usually that file is named roughly MY-APPLICATION-jar-with-dependencies.jar

You can generate the fat jar by calling

mvn clean compile package

Running the fat jar (and your app) is as simple as calling:

java -Dninja.port=9000 -jar MY-APPLICATION-jar-with-dependencies.jar

Incompatibility notice

Please be aware that since Ninja 6.4.3, alongside with Jetty 9.4.12, the dependency allowing Jetty servlets annotations (that should not be useful for your Ninja Framework project) have been excluded from the stack. This was caused by an incompatibility between the version of the java bytecode handler ASM used by this module (6.2) and the java bytecode handler javassist used by Hibernate.

Option 2 - Packaged using Stork Maven Plugin

If you'd like to run your application as a proper daemon on Unix/Mac or as a service on Windows, another option is using the Stork Maven Plugin.

Stork is a collection of utilities for optimizing your “after-build” workflow by filling in the gap between Maven and eventual app execution. In just a couple quick steps, stork will package your Ninja app into a professional .tar.gz file ready for deployment.

Here is an article describing how Ninja apps can be packaged with Stork.

Here is a demo application that integrates with Stork.

Command-line / system property configuration

Regardless of which option you choose, you can customize your application startup via the following command line parameters:

  • ninja.port allows you to select the port on which your application is starting (8080 by default).
  • ninja.host allows you to select the host on which your application will bind (any/0.0.0.0 by default).
  • ninja.idle.timeout allows you to specify the timeout period after which idle HTTP connections will be closed. (in msec, 30000 by default)
  • ninja.mode allows you to select the mode (test, dev, prod) of your application (prod by default).
  • ninja.external.configuration allows you to add an external application configuration (eg -Dninja.external.configuration=conf/production.conf). Please note that even with an external configuration, if you included a conf/application.conf on your classpath (e.g. in your app jar) then it will be loaded first, followed by the external configuration file. By using both files, you'll only need to worry about overriding values – which comes in handy when running in test/production environments.
  • ninja.context allows you to add a context prefix to your application (eg -Dninja.context=/your_context_path).
  • ninja.jetty.configuration allows you to supply a comma-delimited list of jetty.xml configuration files to configure the server. Anything Jetty can do is now available. Please note that if this property is supplied then the host/port property is skipped and you'll need to configure that in the jetty.xml configuration file. (eg -Dninja.jetty.configuration=jetty.xml,jetty-ssl.xml) Please refer to Jetty distribution for example config files. For each jetty configuration file the local filesystem is searched first, followed by the classpath, and if multiple files are included then each one is applied in order.

Init.d script to run Ninja as standalone service on Linux

If you use option #1 and want to register your Ninja standalone application on your Linux box (Debian, Ubuntu) you can use and adapt the following script. The script should be copied at /etc/init.d/ninja and can be run via service ninja start.

#!/bin/bash
# chkconfig: 345 20 80
# description: Ninja start/shutdown script
# processname: java
#
# Installation:
# copy file to /etc/init.d
# chmod +x /etc/init.d/ninja

# chkconfig --add /etc/init.d/ninja
# chkconfig ninja on
#     OR on a Debian system
# sudo update-rc.d ninja defaults

#
# Usage: (as root)
# service ninja start
# service ninja stop
# service ninja status
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# Path to the application
APPLICATION_NAME=my-ninja-service
APPLICATION_PATH=/srv/ninja_applications/${APPLICATION_NAME}
APPLICATION_JAR=my-ninja-service-1.0-SNAPSHOT-jar-with-dependencies.jar

PID_FILE=/var/run/${APPLICATION_NAME}.pid
PORT=9013

# Path to the JVM
JAVA_BIN=/opt/java-oracle/jdk1.7.0/bin/java
PARAMS="-Dninja.port=${PORT} -jar ${APPLICATION_PATH}/${APPLICATION_JAR}"

# User running the Ninja process
USER=ninja

RETVAL=0

start() {
    if [ -f ${PID_FILE} ]; then
        echo "Ninja application ${APPLICATION_NAME} already running"
    else
        DAEMON_START_LINE="start-stop-daemon --chdir=${APPLICATION_PATH} --make-pidfile --pidfile ${PID_FILE} --chuid ${USER} --exec ${JAVA_BIN} --background --start -- ${PARAMS}"
        ${DAEMON_START_LINE}
        RETVAL=$?
        echo -n "Starting Ninja Application: ${APPLICATION_NAME}... "


            if [ $RETVAL -eq 0 ]; then
                echo " - Success"
            else
                echo " - Failure"
            fi
        echo
    fi
    echo

}
stop() {
    kill -9 `cat ${PID_FILE}`
    RETVAL=$?
    rm -rf ${PID_FILE}
    echo -n "Stopping Ninja application: ${APPLICATION_NAME}"

    if [ $RETVAL -eq 0 ]; then
        echo " - Success"
    else
        echo " - Failure"
    fi
        echo
    }

status() {
    if [ -f ${PID_FILE} ]; then
        echo "Ninja application ${APPLICATION_NAME} running"
    else
        echo "Ninja application ${APPLICATION_NAME} not running"
    fi
    echo

}

clean() {
        rm -f ${PID_FILE}
}

case "$1" in
    start)
    start
    ;;
    stop)
    stop
    ;;
    restart|reload)
    stop
    sleep 10
    start
    ;;
    status)
    status
    ;;
    clean)
    clean
    ;;
*)
echo "Usage: $0 {start|stop|restart|status}"
esac