search close

Installing the Java Module as a Jetty Handler

access_time Updated Sep 21, 2021

Requirements

  • Jetty 9.2 or higher

Supported Application Types

For customers looking to use a Jetty specific implementation, we support a HandlerWrapper based install on Jetty 9.2 or higher. We also provide a lower level agent RPC communication API if you are interested in writing an implementation for another Java platform. Contact support if you are interested in doing this.

Agent Configuration

Like other Signal Sciences modules, the Jetty Handler supports both unix domain sockets and TCP sockets for communication with the Signal Sciences Agent. By default, the agent uses Unix Domain Sockets with the address set to unix:/var/run/sigsci.sock. It is possible to override this or specify a TCP socket instead by configuring the -rpc-address parameter in the Agent.

Additionally, ensure the agent is configured to use the default rpc-Version (which is rpc-version=0). This can be done by verifying the parameter rpc-version is not specified in the agent configuration or if it is specified, ensure that is specified with a value of 0. Below is an example Agent configuration that overrides the default unix domain socket value:

````
accesskeyid = “<YOUR AGENT ACCESSKEYID>“
secretaccesskey = “<YOUR AGENT SECRETACCESSKEY>“
rpc-address = "127.0.0.1:9999"
````

Installation

The installation of the Jetty module varies slightly depending upon how you have deployed Jetty (i.e. embedded vs. stand alone).

If you are embedding Jetty within your web application, follow the instructions for “Embedded Jetty”.

Alternatively, if you are deploying your web application to a Jetty instance, follow the instructions for “Standalone Jetty”.

Download

  1. Download the Java module at https://dl.signalsciences.net/sigsci-module-java/sigsci-module-java_latest.tar.gz

  2. Copy jar file to the application classpath. For example in Tomcat this would be %CATALINA_HOME%\webbapps\<APP_FOLDER>\WEB-INF\lib.

  3. Extract sigsci-module-java_latest.tar.gz. There are two options for deploying the jars:

    • Copy sigsci-module-java-{version}-shaded.jar (an uber jar with all the dependencies bundled) to your application’s classpath (e.g., %CATALINA_HOME%\webbapps\<APP_FOLDER>\WEB-INF\lib).

    • Copy sigsci-module-java-{version}.jar and its dependencies in the lib folder to your application’s classpath (e.g., %CATALINA_HOME%\webbapps\<APP_FOLDER>\WEB-INF\lib). If you already have any of the dependency jar files in your application classpath folder (i.e. for Tomcat in the WEB-INF\lib) then it is not necessary to copy them, even if the version numbers are different. The logging jars are optional based on how slf4j is configured.

For Java projects using Maven for build or deployment, the Signal Sciences Java modules can be installed by adding the following to the project pom.xml:

<repositories>
    <repository>
        <id>sigsci-stable</id>
        <url>https://packages.signalsciences.net/release/maven2</url>
    </repository>
</repositories>

<dependency>
  <groupId>com.signalsciences</groupId>
  <artifactId>sigsci-module-java</artifactId>
  <version>1.1.3</version>
</dependency>

Install

The Signal Sciences Jetty module is currently implemented as a Handler. To use this, you will need to make a simple change to your application to wrap your existing Handlers with the Signal Sciences Handler.

A typical Jetty based application will add all of the Handlers to a HandlerList something like this in its code:

    Server server = new Server(InetSocketAddress.createUnresolved("0.0.0.0", 8800));
    ServletContextHandler context = new ServletContextHandler();
    ServletHolder defHolder = new ServletHolder("default", DefaultServlet.class);
    HandlerList handlers = new HandlerList();

    // Servlet: /
    defHolder.setInitParameter("pathInfoOnly", "true");
    defHolder.setInitParameter("dirAllowed", "true");
    defHolder.setInitParameter("acceptRanges", "true");
    context.addServlet(defHolder, "/*");
    context.addServlet(defHolder, "/");

    // Existing App Handlers
    handlers.addHandler(context);
    handlers.addHandler(new DefaultHandler());

    // Add the existing handlers as the server handler
    server.setHandler(handlers);

    try {
    server.start();
    server.join();
    } catch (Exception e) {
    e.printStackTrace();
    } finally {
    server.stop();
    }

To enable the Signal Sciences Handler you would just need to add it around your primary handler with something like this:

    Server server = new Server(InetSocketAddress.createUnresolved("0.0.0.0", 8800));
    ServletContextHandler context = new ServletContextHandler();
    ServletHolder defHolder = new ServletHolder("default", DefaultServlet.class);
    HandlerList handlers = new HandlerList();

    // Servlet: /
    defHolder.setInitParameter("pathInfoOnly", "true");
    defHolder.setInitParameter("dirAllowed", "true");
    defHolder.setInitParameter("acceptRanges", "true");
    context.addServlet(defHolder, "/*");
    context.addServlet(defHolder, "/");

    // Existing App Handlers
    handlers.addHandler(context);
    handlers.addHandler(new DefaultHandler());

    // REMOVED: This is replaced by wrapping with the sigsci handler below
    //server.setHandler(handlers);

    //////////////////////////////////////////////////////////////////////////
    // BEGIN ADDITION: Signal Sciences Handler
    // Need to also add these imports for SignalSciencesHandler and Timeout:
    //   import com.signalsciences.jetty.SignalSciencesHandler;
    //   import com.signalsciences.rpc.util.Timeout;
    //////////////////////////////////////////////////////////////////////////
    // 1. Create a new SignalSciencesHandler
    SignalSciencesHandler sigsciHandler = new SignalSciencesHandler();
    // 2. Specify the URI of the sigsci-agent rpc-address (Unix)
    sigsciHandler.getSigSciConfig().setRpcServerURI(URI.create("unix:/var/run/sigsci.sock"));
    // 3. Specify a timeout
    sigsciHandler.getSigSciConfig().setRpcTimeout(new Timeout(300, TimeUnit.MILLISECONDS));
    // 4. Set rpcVersion to 0
    sigsciHandler.getSigSciConfig().setRpcVersion(0);
    // 5. Wrap the other handlers
    sigsciHandler.setHandler(handlers);
    // 6. Set the SignalSciencesHandler (wrapper) as the server handler
    server.setHandler(sigsciHandler);
    //////////////////////////////////////////////////////////////////////////
    // END ADDITION
    //////////////////////////////////////////////////////////////////////////

    try {
    server.start();
    server.join();
    } catch (Exception e) {
    e.printStackTrace();
    } finally {
    server.stop();
    }

The Signal Sciences Jetty module is currently implemented as a Handler. To use this, you will need to follow the steps below to update your server configuration.

Update Jetty Server Configuration File

In a default Jetty install the server configuration file can be found under {jetty.base}/etc/jetty.xml. The configuration file needs to be updated to wrap the existing Handlers with the Signal Sciences Handler. The stanza in the file that specifies the handler collection should be modified to include the Signal Sciences Handler. Below is an example leveraging the out of the box jetty.xml file:

    <Set name="handler">
      <New id="Wrapper" class="com.signalsciences.jetty.SignalSciencesHandler">
        <Call name="setRpcServerURI">
          <Arg>
            <New class="java.net.URI">
              <Arg>unix:/var/run/sigsci.sock</Arg>
             </New>
          </Arg>
         </Call>
         <Call name="setRpcTimeout">
           <Arg>
             <New class="com.signalsciences.rpc.util.Timeout">
               <Arg type="long">300</Arg>
                 <Arg>
                   <Get class="java.util.concurrent.TimeUnit" name="MILLISECONDS"/>
                 </Arg>
             </New>
           </Arg>
         </Call>
         <Set name="handler">
           <New id="Handlers" class="org.eclipse.jetty.server.handler.HandlerCollection">
             <Set name="handlers">
               <Array type="org.eclipse.jetty.server.Handler">
                 <Item>
                   <New id="Contexts" class="org.eclipse.jetty.server.handler.ContextHandlerCollection"/>
                 </Item>
                 <Item>
                   <New id="DefaultHandler" class="org.eclipse.jetty.server.handler.DefaultHandler"/>
                 </Item>
               </Array>
             </Set>
           </New>
         </Set>
      </New>
    </Set>

Deploy Signal Science Library to the Server ClassPath

Extract and copy one of the two .jar files to your server classpath:

  1. The sigsci-module-java-{version}.jar file plus all the dependencies in the lib folder (or provide your own).

  2. The sigsci-module-java-{version}-shaded.jar (uber jar) from the tarball to your server classpath.

We recommended adding this library to {jetty.base}/lib/ext, as Jetty automatically loads libraries in this path to the server classpath.

Simple Example Server

For a more complete example, see the sigsci-jetty-simple-example JAR files in the distribution. Included are the binaries, source and javadoc for a simple working example. The binary JAR is executable and can be run with something like the following, which will start the simple server and point it at an agent running on TCP port 5000 on the local host (requires an agent started with rpc-address = "127.0.0.1:5000")

    $ java -jar examples/sigsci-jetty-simple-example-{version}.jar
    tcp://127.0.0.1:5000
    00:00:00.384 [main] INFO  c.s.example.SimpleExampleServer - WebRoot is jar:file:/x/sigsci-jetty-simple-example-0.1.3.jar!/webroot/
    00:00:00.403 [main] INFO  c.s.example.SimpleExampleServer - Signal Sciences WAF: enabled
    00:00:00.501 [main] INFO  c.s.example.SimpleExampleServer - Signal Science Simple Example Server started (http://0.0.0.0:8800/)
    00:00:00.986 [qtp123456789-12] INFO  c.s.example.RequestLogger - "GET /test/ HTTP/1.1" 302

This simple test server will respond with a simple HTML page on the root directory and can also be use to do basic tests using the /test/ context. In this test context the following parameters are interpreted:

  • response_time: Time in milliseconds to delay the response - to test timeouts.
  • response_code: The HTTP response code to return in the response.
  • size: The size of the response body in bytes.

For example:

    $ curl -D- "http://127.0.0.1:8800/test/?response_code=302&response_time=10&size=86"
    HTTP/1.1 302 Found
    Date: Sat, 01 Sep 2016 00:00:00 GMT
    Location: /
    Content-Length: 86
    Server: Jetty(9.2.z-SNAPSHOT)