Web Services in Java 2 - Provide REST Resources
Tags: java, beginners, api
Published: 2019-09-30 11:24:18

Hi, welcome back. Hopefully everything we did in [part 1](https://dev.to/funcke/web-services-in-java-1-configure-the-server-1kh7) worked out for you. If anything didn't please leave us a comment and we will look into it as soon as possible. 

In this post we will learn how a REST handler looks in Java and what we can do to tell our server that is exists.

### How are REST Resources structured and how will we access them?

In general, a common approach for structuring Java Applications, is to group actions into logical groups. E.g. all calls working with Users as their target will be grouped into a class named **UsersController**. In general, the most common HTTP Request Methods are being associated with a concrete action type:

- GET - fetch data
- POST - create data
- PUT/PATCH - update data
- DELETE - destroy data

There are of course lots of other request methods but we will mainly focus on those four as they provide nearly all capabilities we need for our small project.

Here we can look at a small example controller:
```java
    @Path("")
    public class ExampleResource {
        @GET
    		@Produces(MediaType.TEXT_HTML)
        public String hello() {
            return "<h1>Hello World</h1>";
        }
    
    		@GET
    		@Path("test")
    		@Produces(MediaType.APPLICATION_JSON)
    		public String test() {
    			return "{ \"Hello\": \"World\"}";
    		}
    }
```

The `@Path` Annotation tells the server the base path the controller is operating at. This annotation can also be put on top of the handler Method. The path this method is listening at will then be created by joining the strings from the annotation on the class and on the method using a`/`

Every Method, that should handle a Request, will also get an annotation with the name of the HTTP Method it supports. In this small example our two methods only support GET.

### Tell the server what we want and what we give

With `@Produces` and `@Consumes` we tell the server what type of content our method wants and what type of content it will return back to the consumer. In the [Javax.ws.rs](http://javax.ws.rs) specification, there is a Enum provided that's called MediaType. It contains all the media types supported by Java. To serve HTML, we will pass `MediaType.TEXT_HTML` to the `@Produces` annotation. If we want to get some JSON from the request, we just tell the server in the `@Consumes` annotation with `MediaType.APPLICATION_JSON`.

### Pass input with the request

That's nice and all, but how the heck can we check if the input from our request is cool?

No biggie. We just gonna create a class for it:
```java
    public class MyFancyInput 
    	private String username;
    	private Integer age;
    	private Boolean acceptTOS;
    	
    	public String getUsername() {
    		return this.username;
    	}
    
    	public void setUsername(String username) {
    		this.username = username;
    	}
    
    	public Integer getAge() {
    		return this.age;
    	}
    
    	public void setAge(Integer age) {
    		this.age = age;
    	}
    
    	public Boolean getAcceptTOS() {
    		return this.acceptTOS;
    	}
    
    	public void setAcceptTOS(Boolean acceptTOS) {
    		this.acceptTOS = acceptTOS;
    	}
    }
```

A request body object is just a plain Java POJO. All the properties must have a getter and a setter method as the deserialization will try to call them. To ensure that a null field will not break our service, we only use non-primitive datatypes. This is because `boolean` for example does not support null types but `Boolean` does.

When you input class is done, we will just tell our operation that we want that as parameter:
```java

    @Path("")
    public class ExampleResource {
        @GET
    		@Produces(MediaType.TEXT_HTML)
        public String hello() {
            return "<h1>Hello World</h1>";
        }
    
    		@GET
    		@Path("test")
    		@Produces(MediaType.APPLICATION_JSON)
    		public String test() {
    			return "{ \"Hello\": \"World\"}";
    		}
    
    		@POST
    		@Path("test")
    		@Consumes(MediaType.APPLICATION_JSON)
    		@Produces(MediaType.APPLICATION_JSON)
    		public MyFancyInput getInput(@NotNull MyFancyInput input) {
    			return input;
    		}
    }
```

Here we just get the input and return it to the client again. With the `@NotNull` annotation we tell the server that the parameter for this method is required and cannot be null.

If the input comes from a special place in the request, we just annotate it with the right annotation. Available annotations are:

- `@BeanParam`
- `@CookieParam`
- `@FormParam`
- `@PathParam`
- `@QueryParam`
- `@MatrixParam`

### Link it all together

We have the resource, we have the data structure, and if you did [Part 1](https://dev.to/funcke/web-services-in-java-1-configure-the-server-1kh7), you also have the server. Now we need to connect it all:

In our main class, we just add  something to our ResourceConfig:
```java
    // Holds all the resources we want to register (currently, there's nothing to do)
    ResourceConfig resourceConfig = new ResourceConfig();
    resourceConfig.register(ExampleResource.class); // our rest resource
    // the parser for JSON and XML request bodies
    resourceConfig.register(JacksonFeature.class);
```
Now when we run our server, we should be able to reach the resources we just create at [`localhost:8080/`](http://localhost:8080/)and on `localhost:8080/test`

After all of this, our project structure should look something like this:

    src
    - main
    	- java
    		- Main.java
    		- ExampleResource.java
    		- MyFancyInput.java
    - test

I hope you had fun and everything worked out for your. Have an awesome day! :D