Fork me on GitHub

First of all it’s important to say that Pippo is based on Servlet 3.1 so, it needs a Servlet container to run properly.

Most server-side Java applications (e.g. web or service-oriented) are intended to run within a container. The traditional way to package these apps for distribution is to bundle them as a WAR file.
Of course you can use the above model for your application development or you can use the simple way.
Rather than your application being deployed to a container, an embedded container is deployed within the application itself.
Pippo comes with Jetty as embedded web server. You can choose another container if you want (for example Tomcat).

See below the classic Hello World in Pippo:

public class HelloWorld {

    public static void main(String[] args) {
        Pippo pippo = new Pippo();
        pippo.GET("/", routeContext -> routeContext.send("Hello World!")); // add a route
        pippo.start();
    }

}

Sure, the number of lines can decrease considerable if you use variant:

public class HelloWorld {

    public static void main(String[] args) {
        Pippo.send("Hello World!");
    }

}

if you consider that in first variant they are too many lines of code.

You can run HelloWorld class from your IDE (or command line) as a normal (desktop) application. The default port for embedded web server is 8338 so open your internet browser and type http://localhost:8338 to see the result.

You can change some aspects (settings) of the embedded web server using:

new Pippo()
    .setPort(8081) // change port to 8081
    .start();

or

Pippo pippo = new Pippo();

WebServer server = pippo.getServer(); // if you want a fine tuning of the web server
server.getSettings().port(8081);
server.setPippoFilterPath("/pippo/*");

pippo.start();

Probably the best approach to specify the server port for an embedded server is via application settings.
Simple set the server.port variable from your src\main\resources\main\conf\application.properties with your value:

# Control the port that Pippo binds
server.port = 8081

Using the same application.properties you can change other server parameters like

# Control the network ip address Pippo binds
# Specify 0.0.0.0 for all available interfaces
server.host = localhost

# Specify the context path of the application
server.contextPath = /

# HTTPS
#server.keystoreFile =
#server.keystorePassword =
#server.truststoreFile = 

By default, Pippo use context path / (root) but you can change it using

  • server.contextPath property
  • programmatically
    new Pippo()
      .setPort(8081)
      .setFilterPath("/pippo/*") // <<<
      .start();
    

Pippo detects automatically the web server using ServiceLoader.
If you want to use a web server in your application, you must add pippo-<server name> as dependency for your project. Other option is to set programmatically the desired web server using Pippo#setServer(WebServer server).

Pippo comes (out of the box) with some web servers (most popular):

To use one of these servers just add a dependency in your project:

<dependency>
    <groupId>ro.pippo</groupId>
    <artifactId>pippo-jetty</artifactId>
    <version>${pippo.version}</version>
</dependency>

In Pippo, the web servers are plug and play and interchangeable (you can change the web server without to change your code).
You never work directly with classes from Jetty, Tomcat or other web server.

Are some situations (very rare) when the behavior provided by an WebServer instance supplied automatically by Pippo need fine tuning. You want to have access to some advanced settings.
In these situations you need to create a custom WebServer.
The idea is to create a custom WebServer if you want to override some aspects (methods) of that server or if you want free access to the servlet container (Jetty, Tomcat, …).

Show below an concrete example of custom JettyServer with persistent sessions

public class MyJettyServer extends JettyServer {

    @Override
    protected ServletContextHandler createPippoHandler() {
        ServletContextHandler handler = super.createPippoHandler();

        // set session manager with persistence
        HashSessionManager sessionManager = new HashSessionManager();
        try {
            sessionManager.setStoreDirectory(new File("sessions-storage"));
        } catch (IOException e) {
            throw new PippoRuntimeException(e);
        }
        sessionManager.setLazyLoad(true); // other possible option
        handler.setSessionHandler(new SessionHandler(sessionManager));

        return handler;
    }

}


public class Main {

    public static void main(String[] args) {
        // the routes are added via MyApplication class
        new Pippo(new MyApplication()).setServer(new MyJettyServer()).start();
    }

}

The WebServer abstraction allows you to add a Servlet or a Filter. Also, WebServer allows you to add servlet listeners in any supported servlet container via addListener(Class<? extends EventListener> listener) method. The Servlet’s listener supported are (the list is not complete):

For the same task but using a more generic approach you can use WebServerInitializer.
Below I present you a code snippet that add a servlet to Pippo:

import org.kohsuke.MetaInfServices;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ro.pippo.core.WebServerInitializer;

import javax.servlet.ServletContext;
import javax.servlet.ServletRegistration;

@MetaInfServices
public class ServletAppender implements WebServerInitializer {

    private static final Logger log = LoggerFactory.getLogger(ServletAppender.class);

    @Override
    public void init(ServletContext servletContext) {
        ServletRegistration.Dynamic demoServlet = servletContext.addServlet("demo", DemoServlet.class);
        demoServlet.setLoadOnStartup(1);
        demoServlet.addMapping("/demo");
        // other possible settings for demoServlet

        log.debug("Added servlet '{}' to '{}'", demoServlet.getClassName(), demoServlet.getMappings().iterator().next());
    }

    @Override
    public void destroy(ServletContext servletContext) {
        // do nothing
    }

}
import ro.pippo.core.Pippo;

import static ro.pippo.core.route.Route.GET;

public class ServletDemo {

    public static void main(String[] args) {
        Pippo pippo = new Pippo();

        // set pippo filter path
        pippo.getServer().setPippoFilterPath("/app/*");

        // add route
        pippo.GET("/", routeContext -> routeContext.send("Hello from Pippo route!"));

        pippo.start();
    }

}

DON’T forget to add @MetaInfServices on your implementation of WebServerInitializer! This annotation generates META-INF/services files automatically.
The full code is available in pippo-demo-servlet project.

If you need to create support for another embedded web server that is not implemented in Pippo or third-party modules than all you need to do is to implement WebServer or to extends AbstractWebServer.

If you want to make your embedded server plugable for Pippo than you must add @MetaInfServices(WebServer.class) annotation to your class

@MetaInfServices(WebServer.class)
public class JettyServer extends AbstractWebServer<JettySettings> {

    // attributes, methods, ...
    
}

A more complex demo project that shows you how to integrate Jersey is available in pippo-demo-jersey project.
This demo is the code source of the article Pippo and Jersey (JAX-RS): A Match Made in Heaven that is availables on DZone.

Server Settings

Different Server settings can be added via application.properties. Below are the settings that are supported:

Jetty

Currently, jetty.maxThreads, jetty.minThreads and jetty.idleTimeout can be passed in application.properties.

  • jetty.maxThreads - maximum number of threads to be allocated with default value 200
  • jetty.minThreads - minimum number of threads to be allocated with default value 8
  • jetty.idleTimeout - idle timeout for each thread before it is stopped with default value 30000

Note: Only when valid maxThreads is passed then, minThreads and idleTimeouts are consumed. In other cases, default values are used

For Detailed description about these settings, please refer here

Undertow

Currently, Pippo supports all UndertowOptions. UndertowOptions can be categorized into 3 subcategories.

  • Server Options - All the server options specified must start with undertow.server.
  • Worker Options - All the worker options specified must start with undertow.worker.
  • Socket Options - All the worker options specified must start with undertow.socket.

Along with these configurations, all other supported settings are mentioned below:

  • undetow.ioThreads - Number of IO threads that needs to be allocated
  • undertow.workerThreads - Number of worker threads that needs to be allocated
  • undertow.bufferSize, undertow.buffersPerRegion and undertow.directBuffers are the other supported settings.

For Detailed description about these settings, please refer here

Sample properties file with undertow settings

undertow.ioThreads=8
undertow.workerThreads=64

undertow.server.NO_REQUEST_TIMEOUT=20000
undertow.socket.TCP_NODELAY=true

Tomcat

Currently, tomcat.clientAuth, tomcat.maxConnections, tomcat.baseFolder, tomcat.keyAlias and tomcat.keyType can be passed in application.properties For Detailed description about these settings, please refer here