Web Services in Java 1 - Configure the server
Tags: java, beginners
Published: 2019-09-29 11:31:51


Java is a joy for backend work. It not only performs well, but also has simmered a long time in the industry, marking it as a battle-tested and solid platform.

What helps making Java so highly efficient and strong as a server-side language, is that it is fully customizable. You can build you application from nearly every combination of available libraries and select only the functionality you want.

This has its advantages. Though it also makes every project some sort of Lego building task. Unfortunately, it does not quite work like with off-the-shelf Lego sets. To use the feature you like or need, you need to pick a package. This gets quite into detail going so far that for a server to correctly running, you need to pick a XML/JSON parser.

To provide a step-by-step guide to your first app, we will, in this series, look at how we can 

- [configure a server] (https://dev.to/funcke/web-services-in-java-1-configure-the-server-1kh7) (embedded [Jetty](https://www.eclipse.org/jetty/))
- [add some REST API to it] (https://dev.to/funcke/web-services-in-java-2-provide-rest-resources-546p) ([Jersey](https://jersey.github.io/))
- provide a database ([Hibernate](http://hibernate.org/))
- inject it with [DI](https://javaee.github.io/hk2/getting-started.html)
- Provide a small ui with [Vue.js](https://vuejs.org/)

### Create Project

As a build and dependency tool for our project, we will use [Gradle](https://gradle.org/). This will allow us to specify dependencies we need for our project. A project using Gradle has the following structure:

```
src
- main
	- java
	- resources
- test
	- java
	- main
build.gradle
settings.gradle
```

In the src directory we will put all our source. Here we have a subdirectory for our tests - **test** - ****and another one for our application - main. In each of the two is a directory for Java code called **java** and for additional file resources **resources.**

In build.gradle we store all our project configuration and in settings.gradle we will configure our project.

Here is the build.gradle used for this series:

```gradle
plugins {
    id 'java'
}

group 'JettyServer'
version '1.0-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.glassfish.jersey.containers:jersey-container-servlet:2.28'
		compile 'org.eclipse.jetty:jetty-server:9.4.19.v20190610'
		compile 'org.eclipse.jetty:jetty-servlet:9.4.19.v20190610'
		compile 'org.glassfish.jersey.inject:jersey-hk2:2.28'
		compile 'jakarta.xml.bind:jakarta.xml.bind-api:2.3.2'
		runtime 'org.glassfish.jaxb:jaxb-runtime:2.3.2'
    compile 'org.eclipse.jetty:jetty-servlets:9.4.19.v20190610'
    compile 'org.glassfish.jersey.media:jersey-media-json-jackson:2.28'
    compile 'org.hibernate:hibernate-core:5.4.4.Final'
    compile 'org.xerial:sqlite-jdbc:3.20.1'
    compile 'com.zsoltfabok:sqlite-dialect:1.0'
}
```

### Create a server in Java

Some of you may have already had experiences with other web technologies like Rails, Flask, Express.js, etc. In these languages the creation of the server is mostly hidden from you. You may create an object and initialize it or everything just runs out of the box. With our server, it is not like that. But let's see:

At first, we need our **Main class** with the **main method,** here we will put all our **start code.**

```java
public class Main {
	public static void main(String[] args) throws Exception {
		
	}
}
```

First, we will need a **Queue** holding all the **threads** we will use to **handle requests.** Be careful, if you make it too large, it will use up all your system resources, if you make it too small, it will not handle all your load. In our case, we will give it a start **capacity** of **20**, let it **grow by 2** and **limit the queue to 80.** We will provide this queue to our **Thread Pool,** it will **handle the distribution of jobs** to our queue. 

```java
public static void main(String[] args) {
//Queue initialization
	BlockingQueue<Runnable> threadPoolQueue = new BlockingArrayQueue<>(20, 2, 80);
// Create ThreadPool for the server to use.
// default idle time as defined in the QueuedThreadPool.
	QueuedThreadPool threadPool = new QueuedThreadPool(20, 2, (int) TimeUnit.MINUTES.toMillis(1), threadPoolQueue);
  threadPool.setName("jetty-test-server");
  threadPool.setDaemon(true);
}
```

Now that we have our system resources set, we need to **create a Server.** We will do this by creating an instance of the **Server** class and a **ServerConnector** class. The connector will open the server to the network.

```java
// Instance of server object - adds the threadPool to use
Server server = new Server(threadPool);
// instance of server connector with server instance to handle connections for
ServerConnector connector = new ServerConnector(server);
// set port to use
connector.setPort(8080);
// add connector to server
server.setConnectors(new Connector[]{connector});
```

Next we add a **ServletContextHandler** for our REST-Resources. This context handler is responsible to provide an **environment for execution of the Request Handler methods**. This includes **Request**, **Response**, **Session** and other important resources.

```java
final ServletContextHandler servletContextHandler = new ServletContextHandler();
servletContextHandler.setContextPath("/");
```

The ContextHandler is set up. The next step is to provide a **ServletHolder** for the ContextHandler to operate on. A ServletHolder is used for **state management** and for correctly **handling paths**. It contains a **ServletContainer** that is itself just an instance of a **Servlet** (a resource callable by the server) that is being initialized with all Resources we want to use in our Application.

```java
// Holds all the resources we want to register (currently, there's nothing to do)
ResourceConfig resourceConfig = new ResourceConfig();
// handles state for servlets
final ServletHolder servletHolder = new ServletHolder(new ServletContainer(resourceConfig));
servletContextHandler.addServlet(servletHolder, "/*");
```

When we have our ServletContextHandler initialized, it is time to provide it to our server, so that it can delegate requests to it. For this, we will use an instance of **HandlerList** and initialize it with our **ServletContextHandler** and pass it to our server.

```java
HandlerList handlers = new HandlerList();
handlers.setHandlers(new Handler[] {servletContextHandler});
server.setHandler(handlers);
```

We got everything in place (Yaaaay :D). Let's start our server:

```java
server.start();
server.join();

```

It now runs on port 8080.