This post will show you one of the easiest way to start using very simply and lightweight HTTP Server for creating e.g. RESTful services application that allows you to share your data over the web.
It does not require downloading any application server installer, or zip file like it is for e.g. Glassfish or Tomcat. All is requited, is to have a maven and java installation on your PC.
To check whether you have it, simply type commends presented in the screen below:
Project that I am talking about is called Project Grizzly, and here is a short introduction from the project home page:
Writing scalable server applications in the Java™ programming language has always been difficult. Before the advent of the Java New I/O API (NIO), thread management issues made it impossible for a server to scale to thousands of users. The Grizzly NIO framework has been designed to help developers to take advantage of the Java™ NIO API. Grizzly’s goal is to help developers to build scalable and robust servers using NIO as well as offering extended framework components: Web Framework (HTTP/S), WebSocket, Comet, and more!
I always thought that the best way to learn new stuff, is by using them, and this is what we are going to do now. For the purpose of this post I will create the simplest RESTful services using Jersey. Grizzly can do much more, but for now we will focus just on the introduction of this project.
I am going to use the IntelliJ as my IDE. First of all, we are going to create a new maven project – we will call it grizzly-service. When you are done creating empty maven project, go to the pom file and add one by one all needed dependencies. Stuff that you need are:
Manage dependencies information for projects that inherits from ‘org.glassfish.jersey’
<dependencyManagement> <dependencies> <dependency> <groupId>org.glassfish.jersey</groupId> <artifactId>jersey-bom</artifactId> <version>${jersey.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
HTTP grizzly container
<dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-grizzly2-http</artifactId> </dependency>
To avoid having InjectionManagerFactory errors
<dependency> <groupId>org.glassfish.jersey.inject</groupId> <artifactId>jersey-hk2</artifactId> </dependency>
To avoid having MessageBodyWriter erros
<dependency> <groupId>org.glassfish.jaxb</groupId> <artifactId>jaxb-runtime</artifactId> <version>2.3.3</version> </dependency>
Finally add plugins, and pom.xml should look like this:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.developersmill</groupId> <artifactId>grizzly-server</artifactId> <version>1.0-SNAPSHOT</version> <name>grizzly-server</name> <properties> <jersey.version>2.34</jersey.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.glassfish.jersey</groupId> <artifactId>jersey-bom</artifactId> <version>${jersey.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>org.glassfish.jersey.containers</groupId> <artifactId>jersey-container-grizzly2-http</artifactId> </dependency> <dependency> <groupId>org.glassfish.jersey.inject</groupId> <artifactId>jersey-hk2</artifactId> </dependency> <dependency> <groupId>org.glassfish.jaxb</groupId> <artifactId>jaxb-runtime</artifactId> <version>2.3.3</version> </dependency> <dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-json-binding</artifactId> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>1.2.1</version> <executions> <execution> <goals> <goal>java</goal> </goals> </execution> </executions> <configuration> <mainClass>com.developersmill.projectgrizzly.GrizzlyServer</mainClass> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <inherited>true</inherited> <configuration> <source>11</source> <target>11</target> </configuration> </plugin> </plugins> </build> </project>
Now we are going to write some java code! At the beging create the Grizzly server class itself:
package com.developersmill.projectgrizzly; import org.glassfish.grizzly.http.server.HttpServer; import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory; import org.glassfish.jersey.server.ResourceConfig; import java.net.URI; public class GrizzlyServer { public static final String BASE_URI = "http://localhost:8080/"; public static HttpServer startServer() { final ResourceConfig rc = new ResourceConfig().packages("com.developersmill.grizzlyserver"); return GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), rc); } public static void main(String[] args) { startServer(); } }
As you can see, we do not need much line of codes to create a simple Application Server!
Start the server container by pressing the RUN button next to the main method in the GrizzlyServer class.
Now lets see the server capabilities by typing in the browser URL http://localhost:8080/application.wadl
Well to be honest, there is nothing much in there … yet! We are going to change that in few minutes! Create new class e.g. ResourceController
package com.developersmill.projectgrizzly; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; @Path("resources") public class ResourceController { @GET @Produces(MediaType.TEXT_PLAIN) public String getIt() { return "Hello Grizzly!"; } }
Restart the server and go to the http://localhost:8080/resources. You should see this:
Yes! It works, and with so little work. We would not call ourselves good programmers if we have not written a Unit test code for that! So lets go. Create ResourceControllerTest class like that:
package com.developersmill.projectgrizzly; import org.glassfish.grizzly.http.server.HttpServer; import org.junit.After; import org.junit.Before; import org.junit.Test; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.WebTarget; import static org.junit.Assert.assertEquals; public class ResourceControllerTest { private HttpServer server; private WebTarget target; @Before public void setUp() { server = GrizzlyServer.startServer(); target = ClientBuilder.newClient().target(GrizzlyServer.BASE_URI); } @Test public void testIt() { String responseMsg = target.path("resources").request().get(String.class); assertEquals("Hello Grizzly!", responseMsg); } @After public void tearDown() { server.shutdownNow(); } }
Then run it, and you should see something like this:
Ok, looks nice, but this is just simple String text. Now lets add some implementation to give us JSON data. First of all we have to add new dependency into the pom.xml file, it should look like this:
<dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-json-binding</artifactId> </dependency>
Then lets create some simple DTO class, e.g. UserDTO:
package com.developersmill.projectgrizzly; public class UserDTO { private final String name; private final int age; public UserDTO(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } }
Now add new producers code to the ResourceController class
package com.developersmill.projectgrizzly; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; @Path("resources") public class ResourceController { @GET @Produces(MediaType.TEXT_PLAIN) public String getIt() { return "Hello Grizzly!"; } @GET @Path("/user") @Produces(MediaType.APPLICATION_JSON) public Response getUser() { return Response.ok().entity(new UserDTO("Pawel", 36)).build(); } }
Then go to the http://localhost:8080/resources/user and see the response
You can also use maven for starting unit tests: mvn install
, and for starting server: exec:java
.That can be much more useful, if you do not want to run it in your IDE.
Code for this project can be found in here
That is all for now. Hope you will find it useful. If you want to lern more about the ‘Project Grizzly’ please go here to check its documentation, examples, and description.