Creating REST with CRNK
Tags: crnk, spring, java
Published: 2019-09-23 17:28:21

_Note: This article was written, and suppose to publish, winter 2018_

Microservices are more than common these days, and at Travelex we use them in various parts of the business. For many of the services we have been using Spring framework to make it easy to get a service up and running fast. As all the microservices are communicating with each other we adopted JSON:API standard. A library which builds upon JSON:API standard is the CRNK library.

_Crnk is a native resource-oriented rest library where resources, their relationships and repositories are the main building blocks._

Combining Crnk and the Spring framework, we have got services up and running fast. Spring Boot creates a runnable service and CRNK helps to handle REST APIs communications. This article, and the next, will go through how to set up a service using CRNK. We will handle a more general sense of what CRNK is and later we going to talk about some challenges we faced when we wanted to do more advanced thing with CRNK.

## CRNK

The minimum requirement to use this library is JAVA 8. We will only look at gradle and maven for this setup. For maven you add in your pom.xml the following packages:

```
<dependency>
  <groupId>io.crnk</groupId>
  <artifactId>crnk-setup-spring-boot2</artifactId>
  <version>${crnk.version}</version>
</dependency>
<dependency>
   <groupId>io.crnk</groupId>
   <artifactId>crnk-client</artifactId>
   <version>${crnk.version}</version>
</dependency>
<dependency>
   <groupId>io.crnk</groupId>
   <artifactId>crnk-validation</artifactId>
   <version>${crnk.version}</version>
</dependency>
<dependency>
   <groupId>io.crnk</groupId>
   <artifactId>crnk-security</artifactId>
   <version>${crnk.version}</version>
</dependency>
<dependency>
   <groupId>io.crnk</groupId>
   <artifactId>crnk-jpa</artifactId>
   <version>${crnk.version}</version>
</dependency>
<dependency>
   <groupId>io.crnk</groupId>
   <artifactId>crnk-monitor-brave4</artifactId>
   <version>${crnk.version}</version>
</dependency>
```

And for gradle you build.gradle looks as followed:

```
compile project(':crnk-setup:crnk-setup-spring-boot2')
compile project(':crnk-jpa')
compile project(':crnk-validation')
compile project(':crnk-home')
compile project(':crnk-ui')
compile project(':crnk-operations')
compile project(':crnk-security')
compile project(':crnk-data:crnk-data-facet')
```

With any of this the project is ready to use CRNK. And to use CRNK is quite easy. As a minimum it only need an annotation on a model class and a repository connected with that model class. A repository will handle the data for said model. It could either store it in itself as a hashmap or it could store the data in a data structure, e.g database.

## Model and data

The model is the representation of the data the application have. The data needs to be stored in a repository which either hold the data in memory or can be connected to a database.

```
// Copyright (c) 2018 Travelex Ltd
package com.travelex.store.model;
import io.crnk.jpa.annotations.JpaResource;
import lombok.Data;
import javax.persistence.Entity;
@Data
@JpaResource(type = "person")
@Entity
public class Person {
  private String name;
  private int age;
}
```

In the above example the JpaResource will be the external connection to this resource when making POST, PUT or GET request. The annotation entity will connect us straight to the database we have as our underlying structure to hold data. We don't need to construct a repository class if we configure with using Entity.

### Lombok

The Lombok package is what we use throughout our services which help us greatly to reduce code. The way lombok work is generating code for our class so we don't have to write about getters and setters and all those method a class is suppose to have. The annotation of Data bundles together different annotation to create getter, setters, toString, constructors and more so we only have to define the attributes of our model.


## Repository

We now need to connect our resource to its data, and we'll do this by creating a repository. For simplicity, our repository will store our data in memory within a hashmap.

A resource, which the model is, need to connect to its data. This is usually done with a repository. The repository will either hold the data in memory, as hashmap, or it can be connected to a data structure, e.g database. A normal repository can look like:

```
// Copyright (c) 2018 Travelex Ltd
package com.travelex.store.model;
import io.crnk.core.queryspec.QuerySpec;
import io.crnk.core.repository.ResourceRepositoryBase;
import io.crnk.core.resource.list.ResourceList;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
@Component
public class PersonRepository extends ResourceRepositoryBase<Person, int> {
  private Map<int, String> list = new HashMap<>();
  public PersonRepository() {
    super(Person.class);
  }

  @Override
  public void delete(int age) {
    list.remove(age);
  }

  @Override
  public <S extends Person> S save(S person) {
    list.put(person.getAge(), person.getName());
  }

  @Override
  public ResourceList<Person> findAll(QuerySpec querySpec) {
    return querySpec.apply(list.values());
  }
  ...
}
```

## Filtering and CRNK

The JpaResource gives us features from CRNK how to query the data. Default options is filtering and sorting resources. With filtering you can have: EQ for equal values, LIKE for patterns, LT for lower than, LE for lower and equal, GT for greater than and GE for greater and equal. A typical filter call

```
/person?filter[EQ][age]=25
```

will look through the database for every entity where the data for age is equal to 25.

You can add your own filter operator as long as you handle the query in the repository correctly. Meaning that filterOperators are both on the request going into your server and the query request to the database. This will be handle in later.

## Summary

With CRNK library you can create the REST APIs with minimum effort. It helps construct REST API for the service and the only thing we have to worry about is the data we need said service to handle. If you are using the Spring framework as we did with our test service here at minimum you would need less than 5 classes: the main class that start the SpringBoot application, the model class which represent our data and a configuration class that connect with a database.

CRNK is good to create simple REST APIs services that can hold data. It easy to use with SpringBoot and as developers we don't need to focus on the code to connect to our service. But as with CRNK being simple to connect with SpringBoot and setting up a service, if you need to configure something which is not standard in CRNK there will be a need to hack around this.