home.


Tagged: jetty


Scala: Simplest Jersey service with Jetty returning JSON via Jackson

If you want a quick web service with Jersey in Jetty returning JSON, you must:

  • Define the basic Jersey class with annotations.
  • Use JettyHttpContainerFactory to start the Jetty service.

Let’s put it all together, in a file called rest.scala.

import java.util.ArrayList
import javax.servlet.http.{HttpServletRequest, HttpServletResponse}
import javax.ws.rs.{ApplicationPath, GET, Path, Produces}
import javax.ws.rs.core.{MediaType, UriBuilder}
import javax.ws.rs.{ApplicationPath, GET, Path, Produces}
import javax.ws.rs.core.{MediaType}
import org.eclipse.jetty.server.handler.AbstractHandler
import org.eclipse.jetty.server.{Server, Request}
import org.glassfish.jersey.server.ResourceConfig
import org.glassfish.jersey.jetty.JettyHttpContainerFactory

object rest {

  @Path("/") class Hello {
    @Path("hello") @GET @Produces(Array(MediaType.APPLICATION_JSON))
    // Returns ArrayList, not a scala List, since Jackson can't convert that
    def example() : ArrayList[String] = {
      var al = new ArrayList[String]()
      al.add("hmm")
      return al
    }
  }

  // Not run from a scala script, since that strangely can't find Hello
  def main(args: Array[String]) : Unit = {
    JettyHttpContainerFactory.createServer(
      UriBuilder.fromUri("http://localhost/").port(9998).build(),
      new ResourceConfig(classOf[Hello])
    )
  }
}

You need these dependencies, which you can use with this via gradle -b deps.gradle copyDependencies:

    compile 'org.glassfish.jersey.bundles:jaxrs-ri:2.23.1'
    compile 'org.glassfish.jersey.containers:jersey-container-jetty-http:2.23.1'
    compile 'org.glassfish.jersey.media:jersey-media-json-jackson:2.16'

Or just download them all via this bash script (urls obtained via the stderr output of the above script):

wget -P dependencies/ https://repo1.maven.org/maven2/javax/inject/javax.inject/1/javax.inject-1.jar
wget -P dependencies/ https://repo1.maven.org/maven2/javax/annotation/javax.annotation-api/1.2/javax.annotation-api-1.2.jar
wget -P dependencies/ https://repo1.maven.org/maven2/javax/ws/rs/javax.ws.rs-api/2.0.1/javax.ws.rs-api-2.0.1.jar
wget -P dependencies/ https://repo1.maven.org/maven2/javax/validation/validation-api/1.1.0.Final/validation-api-1.1.0.Final.jar
wget -P dependencies/ https://repo1.maven.org/maven2/javax/servlet/javax.servlet-api/3.1.0/javax.servlet-api-3.1.0.jar
wget -P dependencies/ https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-http/9.2.14.v20151106/jetty-http-9.2.14.v20151106.jar
wget -P dependencies/ https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-io/9.2.14.v20151106/jetty-io-9.2.14.v20151106.jar
wget -P dependencies/ https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-server/9.2.14.v20151106/jetty-server-9.2.14.v20151106.jar
wget -P dependencies/ https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-util/9.2.14.v20151106/jetty-util-9.2.14.v20151106.jar
wget -P dependencies/ https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-continuation/9.2.14.v20151106/jetty-continuation-9.2.14.v20151106.jar
wget -P dependencies/ https://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-core/2.3.2/jackson-core-2.3.2.jar
wget -P dependencies/ https://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-databind/2.3.2/jackson-databind-2.3.2.jar
wget -P dependencies/ https://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-annotations/2.3.2/jackson-annotations-2.3.2.jar
wget -P dependencies/ https://repo1.maven.org/maven2/com/fasterxml/jackson/jaxrs/jackson-jaxrs-base/2.3.2/jackson-jaxrs-base-2.3.2.jar
wget -P dependencies/ https://repo1.maven.org/maven2/com/fasterxml/jackson/jaxrs/jackson-jaxrs-json-provider/2.3.2/jackson-jaxrs-json-provider-2.3.2.jar
wget -P dependencies/ https://repo1.maven.org/maven2/com/fasterxml/jackson/module/jackson-module-jaxb-annotations/2.3.2/jackson-module-jaxb-annotations-2.3.2.jar
wget -P dependencies/ https://repo1.maven.org/maven2/org/glassfish/jersey/core/jersey-server/2.23.1/jersey-server-2.23.1.jar
wget -P dependencies/ https://repo1.maven.org/maven2/org/glassfish/jersey/core/jersey-client/2.23.1/jersey-client-2.23.1.jar
wget -P dependencies/ https://repo1.maven.org/maven2/org/glassfish/jersey/core/jersey-common/2.23.1/jersey-common-2.23.1.jar
wget -P dependencies/ https://repo1.maven.org/maven2/org/glassfish/jersey/containers/jersey-container-servlet-core/2.23.1/jersey-container-servlet-core-2.23.1.jar
wget -P dependencies/ https://repo1.maven.org/maven2/org/glassfish/jersey/containers/jersey-container-servlet/2.23.1/jersey-container-servlet-2.23.1.jar
wget -P dependencies/ https://repo1.maven.org/maven2/org/glassfish/jersey/containers/jersey-container-jetty-http/2.23.1/jersey-container-jetty-http-2.23.1.jar
wget -P dependencies/ https://repo1.maven.org/maven2/org/glassfish/jersey/bundles/jaxrs-ri/2.23.1/jaxrs-ri-2.23.1.jar
wget -P dependencies/ https://repo1.maven.org/maven2/org/glassfish/jersey/bundles/repackaged/jersey-guava/2.23.1/jersey-guava-2.23.1.jar
wget -P dependencies/ https://repo1.maven.org/maven2/org/glassfish/jersey/media/jersey-media-json-jackson/2.16/jersey-media-json-jackson-2.16.jar
wget -P dependencies/ https://repo1.maven.org/maven2/org/glassfish/jersey/media/jersey-media-jaxb/2.23.1/jersey-media-jaxb-2.23.1.jar
wget -P dependencies/ https://repo1.maven.org/maven2/org/glassfish/jersey/ext/jersey-entity-filtering/2.16/jersey-entity-filtering-2.16.jar
wget -P dependencies/ https://repo1.maven.org/maven2/org/glassfish/hk2/hk2-api/2.4.0-b34/hk2-api-2.4.0-b34.jar
wget -P dependencies/ https://repo1.maven.org/maven2/org/glassfish/hk2/hk2-locator/2.4.0-b34/hk2-locator-2.4.0-b34.jar
wget -P dependencies/ https://repo1.maven.org/maven2/org/glassfish/hk2/osgi-resource-locator/1.0.1/osgi-resource-locator-1.0.1.jar
wget -P dependencies/ https://repo1.maven.org/maven2/org/glassfish/hk2/hk2-utils/2.4.0-b34/hk2-utils-2.4.0-b34.jar
wget -P dependencies/ https://repo1.maven.org/maven2/org/glassfish/hk2/external/aopalliance-repackaged/2.4.0-b34/aopalliance-repackaged-2.4.0-b34.jar
wget -P dependencies/ https://repo1.maven.org/maven2/org/glassfish/hk2/external/javax.inject/2.4.0-b34/javax.inject-2.4.0-b34.jar
wget -P dependencies/ https://repo1.maven.org/maven2/org/javassist/javassist/3.18.1-GA/javassist-3.18.1-GA.jar

Finally run the program with scala -cp "dependencies/*" rest.scala. You should see:

2016-08-14 16:34:13.759:INFO::main: Logging initialized @791ms
2016-08-14 16:34:14.160:INFO:oejs.Server:main: jetty-9.2.14.v20151106
2016-08-14 16:34:14.181:INFO:oejs.ServerConnector:main: Started ServerConnector@5efa40fe{HTTP/1.1}{0.0.0.0:9998}
2016-08-14 16:34:14.182:INFO:oejs.Server:main: Started @1213ms

You can test it via:

curl localhost:9998/hello
["hmm"]
scala jersey jetty jackson

Simplest Jetty server in Scala

Let’s first download the jetty runner:

wget http://central.maven.org/maven2/org/eclipse/jetty/jetty-runner/9.4.0.M0/jetty-runner-9.4.0.M0.jar

Then create a Scala file, server.scala, that creates a AbstractHandler class, which handles incoming request, and outputs some text.

import org.eclipse.jetty.server.handler.AbstractHandler
import org.eclipse.jetty.server.{Server, Request}
import javax.servlet.http.{HttpServletRequest, HttpServletResponse}

class Handler extends AbstractHandler {
  var html = <h1>Something, innit</h1>

  override def handle(target: String,
                      req: Request,
                      httpReq: HttpServletRequest,
                      httpRes: HttpServletResponse) = {
    httpRes.setContentType("text/html")
    httpRes.setStatus(HttpServletResponse.SC_OK)
    httpRes.getWriter().println(html.toString)
    req.setHandled(true)
  }
}

val server = new Server(8080)
server.setHandler(new Handler)
server.start

Finally run the Scala program.

scala -cp jetty-runner-9.4.0.M0.jar server.scala

You can now visit http://localhost:8080 to reach it. It’ll take about 15 seconds to load.

scala jetty

A single page Java/Jetty/Jersey REST app with no web.xml descriptor

First create the build.gradle file in your directory:

apply plugin: 'war'
apply plugin: 'eclipse'

repositories {
   mavenCentral()
}

dependencies {
    compile 'org.glassfish.jersey.media:jersey-media-json-jackson:2.16'
    compile 'org.glassfish.jersey.bundles:jaxrs-ri:2.16'
}

compileJava {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
}

Then, in src/main/java/com/example, create App.java:

package com.example;

import java.util.ArrayList;
import java.util.List;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import org.glassfish.jersey.server.ResourceConfig;

@ApplicationPath("rest") 
public class App extends ResourceConfig {
  public App() { packages("com.example"); }

  @Path("example")
  public static class Hello {

      @GET
      @Produces(MediaType.APPLICATION_JSON)
      public List<String> example() {
        List<String> l = new ArrayList<>();
        l.add("one"); l.add("two");
        return l; 
      }

  }  

}

Now

  1. Create the war file with gradle
  2. Download the Jetty runner jar
  3. Run the war file with the jetty runner (takes about 15 seconds to init usually)
  4. Use curl to test the app

From the command line:

gradle build war
wget http://central.maven.org/maven2/org/eclipse/jetty/jetty-runner/9.3.0.M1/jetty-runner-9.3.0.M1.jar
java -jar jetty-runner-9.3.0.M1.jar --port 8081 build/libs/your-directory-name.war
curl localhost:8081/rest/example && echo

The above curl command should print:

["one","two"]
jetty jersey gradle java

PART 1: Quick start a RESTful project with Jersey, Jetty and Gradle

(This is part of a series http://blog.denevell.org/category_java-web-quick-start.html)

Make the project directory and the directory structure for Gradle:

mkdir YOUR_PROJECT_DIR && cd YOUR_PROJECT_DIR
mkdir -p {src/main/java/com/example/YOURPROJECT/,src/main/resources/META-INF,src/main/webapp/WEB-INF,logs}

Next create the Gradle build file, including the war and eclipse plugins, and the logging, jersey and jersey json jars.

echo "
apply plugin: 'war'
apply plugin: 'eclipse'

repositories {
    mavenCentral()
    // Below needed in later tutorials
    maven {
        url 'http://download.eclipse.org/rt/eclipselink/maven.repo'
    }
}

dependencies {
    compile 'log4j:log4j:1.2.7'
    compile 'org.slf4j:slf4j-log4j12:1.6.6'
    compile 'org.glassfish.jersey.containers:jersey-container-servlet:2.6'
    // Following aren't needed atm, but will be in later parts.
    compile 'org.glassfish.jersey.media:jersey-media-json-jackson:2.6'
    compile 'org.eclipse.jetty:jetty-jsp:9.1.0.M0'
    compile 'postgresql:postgresql:9.1-901-1.jdbc4'
    compile 'org.eclipse.persistence:eclipselink:2.4.0'        
}" > build.gradle

Next create the log4j.properties file.

echo "
log4j.rootCategory=INFO, rollingFile 

log4j.appender.rollingFile=org.apache.log4j.RollingFileAppender
log4j.appender.rollingFile.File=logs/YOUR_LOG_FILE.log
log4j.appender.rollingFile.MaxFileSize=10MB
log4j.appender.rollingFile.MaxBackupIndex=2
log4j.appender.rollingFile.layout = org.apache.log4j.PatternLayout
log4j.appender.rollingFile.layout.ConversionPattern=%d{yyyy-MM-dd HH-mm-ss} %-5p [%t] %c %x - %m%n
" > src/main/resources/log4j.properties

Next create the web.xml file starting Jersey by pointing to a yet-to-be-created application class, specifying the package where the request classes will live, and defining a path for the REST calls.

echo '
<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
    version="2.4">

    <display-name>YOUR_SERVICE</display-name>

    <servlet>
       <servlet-name>YOUR_SERVLET_NAME</servlet-name>
       <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>com.example.YOURPROJECT.JerseyApplication</param-value>
        </init-param>     
        <init-param>
           <param-name>jersey.config.server.provider.packages</param-name>
         <param-value>com.example.YOURPROJECT</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
       <servlet-name>YOUR_SERVLET_NAME</servlet-name>
       <url-pattern>/YOUR_PATH/*</url-pattern>
    </servlet-mapping>

</web-app>
' > src/main/webapp/WEB-INF/web.xml

Now create that JerseyApplication file we referred to. (Specifying the JerseyApplication isn’t strictly necessary, nor is registering Jackson for this setup, but if we’re using JSON later on, it will be)

echo "
package com.example.YOURPROJECT;

import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.server.ResourceConfig;

public class JerseyApplication extends ResourceConfig {
    public JerseyApplication() {
       register(JacksonFeature.class);
    }
}

" > src/main/java/com/example/YOURPROJECT/JerseyApplication.java

Now create a simple Jersey request.

echo '
package com.example.YOURPROJECT;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import org.apache.log4j.Logger;

@Path("example")
public class ExampleRequest {

    @Path("{example}")
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String example(@PathParam("example") String example) {
       Logger.getLogger(getClass()).info("Working???");
       return example + "!!!!";
    }

}
' > src/main/java/com/example/YOURPROJECT/ExampleRequest.java

Build the project, which creates a WAR file, download the jetty runner, and then use the runner to run the WAR on port 8081.

gradle build
wget http://repo1.maven.org/maven2/org/eclipse/jetty/jetty-runner/9.1.0.M0/jetty-runner-9.1.0.M0.jar
java -jar jetty-runner-9.1.0.M0.jar --port 8081 build/libs/YOUR_PROJECT_DIR.war

Now you should be able envoke the request you defined earlier by visiting its url (and check the log file after you do so).

http://localhost:8081/YOUR_PATH/example/some_text

If you want to use this project in Eclipse, run ‘gradle eclipse’ and import the project into Eclipse.

jersey java jetty gradle java-web-quick-start

Jetty 9: Enabling SSL in Embedded Jetty

First create a HttpConfiguration with a HTTP configuration that explains its secure scheme and port:

HttpConfiguration http_config = new HttpConfiguration();
http_config.setSecureScheme("https");
http_config.setSecurePort(8443);

Then we’ll create another HttpConfiguration for https that extends from the above but adds a SecureRequestCustomizer

HttpConfiguration https_config = new HttpConfiguration(http_config);
https_config.addCustomizer(new SecureRequestCustomizer());          

Next create a SslContextFactory that points to your Java keystore

SslContextFactory sslContextFactory = new SslContextFactory("/its_dir/cert.keystore");
sslContextFactory.setKeyStorePassword("password");

Note you can prefix the password with OBF: if you’re going to use the Jetty obfuscated password.

Next we’re creating the ServerConnector, passing in the Server class, a SslConnectorFactory and a HttpConnectionFactory.

ServerConnector httpsConnector = new ServerConnector(server, 
       new SslConnectionFactory(sslContextFactory, "http/1.1"),
       new HttpConnectionFactory(https_config));
httpsConnector.setPort(8443);
httpsConnector.setIdleTimeout(50000);           

Finally use this connector, maybe along with a normal Http ServerConnector, to the Server.

server.setConnectors(new Connector[]{ httpsConnector });
java jetty ssl https

Page 1 of 2
Next