Over this weekend (April/2017) I tried to write simple RESTful webservice (by the way I don't remember writing REST for work in last few years). So, I started where everyone starts i.e. google. With in no time, I am able to write a simple REST service with jetty server running in embedded mode.
Then I want to find more examples of how to add a HTML form and submit to a REST service i.e. use POST, not just GET. I found few examples, but all of them starting the servlet engine (jetty or grizzly or Tomcat) as a server and serving HTML or servlet content. NOT a single example that shows how to serve HTML and REST service while running jetty in embedded mode. So I decided to code one and blog it.
I used maven (3.x) and java 8.
You can download the maven project (with ALL dependencies) from here:
https://github.com/gputty/SimpleRestService
Now lets go how to do it step by step (github project may NOT match exactly)
Step #1
Create a project using maven command:
mvn archetype:generate -DgroupId=com.yaams -DartifactId=SimpleRestService -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
Lets first build pom.xml with all dependencies.
Below tags tell you what versions used.
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.jetty.version>9.4.3.v20170317</project.jetty.version>
<project.jersey.version>2.7</project.jersey.version>
</properties>
First add all jetty dependencies:
<!-- jetty server dependencies -->
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${project.jetty.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>${project.jetty.version}</version>
</dependency>
Then add jersey dependencies:
<!-- jersey dependencies -->
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>${project.jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<version>${project.jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-jetty-http</artifactId>
<version>${project.jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>${project.jersey.version}</version>
</dependency>
Below are optional jars :
<!-- below are optional dependencies -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.10</version>
</dependency>
Step # 2
Now look at main code:
Add context handlers for web folder
// adding "web" folder
ResourceHandler handler = new ResourceHandler();
handler.setDirectoriesListed(true);
handler.setWelcomeFiles(new String[] { "index.html" });
handler.setResourceBase("./web");
ContextHandler context = new ContextHandler();
context.setContextPath("/web");
context.setHandler(handler);
contextsCollection.addHandler(context);
Add jersey servlet context handler :
So any REST request will be handled like any other request by servlet engine. ONLY difference is before handing over to servlet engine, we need to hand over it to jeresey servlet org.glassfish.jersey.servlet.ServletContainer and that will figure out which service we are trying to invoke and rest will be handled as usual.
ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
servletContextHandler.setContextPath("/rest");
ServletHolder jerseyServlet = servletContextHandler.addServlet(org.glassfish.jersey.servlet.ServletContainer.class, "/*");
jerseyServlet.setInitOrder(0);
jerseyServlet.setInitParameter("jersey.config.server.provider.classnames", ContactService.class.getCanonicalName());
Once you have these context handlers add them to ContextHandlerCollection.
If someone wonders what is "embedded mode". it is simply you start jetty server in your own java program rather than starting it as a server from command line. So when you want to shutdown your server, you will just kill your java program.
Now create jetty server in embedded mode and set the handlers:
Server jettyEmbeddedServer = new Server(8080);
jettyEmbeddedServer.setHandler(mainProgram.contextsCollection);
Now start it:
try {
jettyEmbeddedServer.start();
jettyEmbeddedServer.join();
} finally {
jettyEmbeddedServer.destroy();
}
That's it.
Then I want to find more examples of how to add a HTML form and submit to a REST service i.e. use POST, not just GET. I found few examples, but all of them starting the servlet engine (jetty or grizzly or Tomcat) as a server and serving HTML or servlet content. NOT a single example that shows how to serve HTML and REST service while running jetty in embedded mode. So I decided to code one and blog it.
I used maven (3.x) and java 8.
You can download the maven project (with ALL dependencies) from here:
https://github.com/gputty/SimpleRestService
Now lets go how to do it step by step (github project may NOT match exactly)
Step #1
Create a project using maven command:
mvn archetype:generate -DgroupId=com.yaams -DartifactId=SimpleRestService -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
Lets first build pom.xml with all dependencies.
Below tags tell you what versions used.
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.jetty.version>9.4.3.v20170317</project.jetty.version>
<project.jersey.version>2.7</project.jersey.version>
</properties>
First add all jetty dependencies:
<!-- jetty server dependencies -->
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>${project.jetty.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>${project.jetty.version}</version>
</dependency>
Then add jersey dependencies:
<!-- jersey dependencies -->
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>${project.jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet-core</artifactId>
<version>${project.jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-jetty-http</artifactId>
<version>${project.jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>${project.jersey.version}</version>
</dependency>
Below are optional jars :
<!-- below are optional dependencies -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.10</version>
</dependency>
Step # 2
Now look at main code:
Add context handlers for web folder
// adding "web" folder
ResourceHandler handler = new ResourceHandler();
handler.setDirectoriesListed(true);
handler.setWelcomeFiles(new String[] { "index.html" });
handler.setResourceBase("./web");
ContextHandler context = new ContextHandler();
context.setContextPath("/web");
context.setHandler(handler);
contextsCollection.addHandler(context);
Add jersey servlet context handler :
So any REST request will be handled like any other request by servlet engine. ONLY difference is before handing over to servlet engine, we need to hand over it to jeresey servlet org.glassfish.jersey.servlet.ServletContainer and that will figure out which service we are trying to invoke and rest will be handled as usual.
ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
servletContextHandler.setContextPath("/rest");
ServletHolder jerseyServlet = servletContextHandler.addServlet(org.glassfish.jersey.servlet.ServletContainer.class, "/*");
jerseyServlet.setInitOrder(0);
jerseyServlet.setInitParameter("jersey.config.server.provider.classnames", ContactService.class.getCanonicalName());
Once you have these context handlers add them to ContextHandlerCollection.
If someone wonders what is "embedded mode". it is simply you start jetty server in your own java program rather than starting it as a server from command line. So when you want to shutdown your server, you will just kill your java program.
Now create jetty server in embedded mode and set the handlers:
Server jettyEmbeddedServer = new Server(8080);
jettyEmbeddedServer.setHandler(mainProgram.contextsCollection);
Now start it:
try {
jettyEmbeddedServer.start();
jettyEmbeddedServer.join();
} finally {
jettyEmbeddedServer.destroy();
}
That's it.