Friday, November 3, 2017

Create a small HTTPS server with Java 7 & Jetty

Sometimes in web development we need a small webserver to test our product in a browser. Of course there are several implementations (WAMP, XAMP, etc.), but as a Java developer we don’t want PHP or MySQL to our PC. In this tutorial we’ll create a runnable JAR, which’ll serves our HTTP / HTTPS requests.

Create the Maven project

Start your favorite IDE (Eclipse, or whatever), and create a Maven based project. Open the recently created pom.xml file, and add the following lines:

...
<properties>
      <jettyVersion>7.2.0.v20101020</jettyVersion>
   </properties>

   <dependencies>
      <dependency>
          <groupId>org.eclipse.jetty</groupId>
          <artifactId>jetty-server</artifactId>
          <version>${jettyVersion}</version>
      </dependency>
      <dependency>
          <groupId>org.eclipse.jetty</groupId>
          <artifactId>jetty-webapp</artifactId>
          <version>${jettyVersion}</version>
      </dependency>
   </dependencies>
<build>
      <plugins>
          <plugin>
              <!-- This plugin is needed for the servlet example -->
              <groupId>org.mortbay.jetty</groupId>
              <artifactId>jetty-maven-plugin</artifactId>
              <version>${jettyVersion}</version>
          </plugin>
      </plugins>
   </build>
...

This is ok, but it’s not a runnable JAR. The following lines’ll make it runnable, so add it under the <plugins> tag:
...
          <plugin>
              <groupId>org.codehaus.mojo</groupId>
              <artifactId>exec-maven-plugin</artifactId>
              <version>1.1</version>
              <executions>
                  <execution>
                      <goals>
                          <goal>java</goal>
                      </goals>
                  </execution>
              </executions>
              <configuration>
                  <mainClass>jettytest.Main</mainClass>
              </configuration>
          </plugin>
          <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-dependency-plugin</artifactId>
              <executions>
                  <execution>
                      <id>copy-dependencies</id>
                      <phase>prepare-package</phase>
                      <goals>
                          <goal>copy-dependencies</goal>
                      </goals>
                      <configuration>
                          <outputDirectory>
                              ${project.build.directory}/libs
                          </outputDirectory>
                      </configuration>
                  </execution>
              </executions>
          </plugin>
          <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-jar-plugin</artifactId>
              <version>2.4</version>
              <configuration>
                  <archive>
                      <manifest>
                          <addClasspath>true</addClasspath>
                          <classpathPrefix>libs/</classpathPrefix>
                          <mainClass>jettytest.Main</mainClass>
                      </manifest>
                  </archive>
              </configuration>
              <executions>
                  <execution>
                      <id>package-jar</id>
                      <phase>package</phase>
                      <goals>
                          <goal>jar</goal>
                      </goals>
                  </execution>
              </executions>
          </plugin>
          <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-assembly-plugin</artifactId>
              <executions>
                  <execution>
                      <phase>package</phase>
                      <goals>
                          <goal>single</goal>
                      </goals>
                      <configuration>
                          <archive>
                              <manifest>
                                  <mainClass>
                                      jettytest.Main
                                  </mainClass>
                              </manifest>
                          </archive>
                          <descriptorRefs>
                              <descriptorRef>jar-with-dependencies</descriptorRef>
                          </descriptorRefs>
                      </configuration>
                  </execution>
              </executions>
          </plugin>

Ok, then start a compile with
mvn clean install

You'll get a compile error, because you don't have any Main class, so in the next section we'll create it.

The Main.java

Create a new Java file called Main and modify it’s body to this:
package jettytest;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ssl.SslSocketConnector;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;

public class Main {

   public static void main(final String[] args) throws Exception {
      final Server server = new Server(“8081”);

      final ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
      context.setResourceBase("C:/webdir/");
      context.setContextPath("/");

      final ServletHolder holderHome = new ServletHolder(DefaultServlet.class);
      holderHome.setInitParameter("resourceBase", args[1]);
      holderHome.setInitParameter("dirAllowed", "true");
      holderHome.setInitParameter("pathInfoOnly", "true");
      context.addServlet(holderHome, "/*");

      server.setHandler(context);

      server.start();
      server.join();
   }
}

Keystore

Open a command line and type:

keytool -genkey -keyalg RSA -alias selfsigned -keystore keystore.jks -storepass password -validity 3600 -keysize 2048


This’ll create a new cert for 10 years named keystore.jks with the credential “password”. Put the generated file into a directory, for example: C:/keystore .

Compile the project and run the Main.java in your IDE or run the generated JAR file with:
java -jar jettytest.jar

Make it HTTPS

Cool, we got an HTTP server, but we want HTTPS. Extend our code with the highlighted lines.

package jettytest;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ssl.SslSocketConnector;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;

public class Main {
   private static SslSocketConnector createConnector(final String[] args) {
      final SslSocketConnector connector = new SslSocketConnector();
      connector.setPort(8443);
      connector.setMaxIdleTime(30000);
      connector.setKeystore(args[1] + "keystore/keystore.jks");
      connector.setKeyPassword("password");
      connector.setTrustPassword("password");
      connector.setTruststore(args[1] + "keystore/keystore.jks");
      return connector;
   }

   public static void main(final String[] args) throws Exception {
      final Server server = new Server(Integer.valueOf(args[0]).intValue());

      final ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
      context.setResourceBase(args[1] + "");
      context.setContextPath("/");

      final ServletHolder holderHome = new ServletHolder(DefaultServlet.class);
      holderHome.setInitParameter("resourceBase", args[1]);
      holderHome.setInitParameter("dirAllowed", "true");
      holderHome.setInitParameter("pathInfoOnly", "true");
      context.addServlet(holderHome, "/*");

      server.setHandler(context);

      server.addConnector(createConnector(args));

      server.start();
      server.join();
   }
}

Try

Open again a command line and run the following command:
java -jar jettytest.jar/

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Configure and use VSCode for Java web development

Embarking on Java web development often starts with choosing the right tools that streamline the coding process while enhancing productivity...