Voyager server spring boot starter

Overview

voyager-server-spring-boot-starter

What is Voyager Server?

Voyager Server is a set of helper classes and interfaces that help creating REST endpoints for models, including easy Access Control Level (ACL) and before/after create/read/update/delete hooks (see ACLs and Hooks for details).

The following endpoints are generated:

  • POST /
    • Receives the entity to be created in the body
  • GET /
    • Supports sort_by query parameter with the following format sort_by= : (for example, sort_by=createdAt:desc)
    • Supports pagination by query parameters:
      • page_no
        • If not present, will default to 0
      • page_size
        • If not present, will default to 20
    • Supports filtering by specifying the fields to filter by as query parameters in the format = or = : , for example:
      • name=John
      • name=eq:"John"
        • Note that when the operation is explicit, strings must be warped in double quotes
      • name=neq:"John"
      • name=in:"John","Bob"
        • Multiple values can be delimited by comma, if the operation is of such nature that it accepts an array of terms
      • age=gte:10
        • If no double quotes are used (such as in this case) the value will be parsed to a number
      • gender=eq:null
        • In no double quotes are used (such as in this case), and the value is "null", then it will be parsed as null
  • GET /{id}
  • PUT /{id}
    • Receives the full (not just the changed fields) updated entity in the body
    • The id of an entity will not be changed, event if send in the body
  • DELETE /{id}

Add to your project

Gradle

Step 1. Add the JitPack repository to your build file

allprojects {
    repositories {
        ...
    	maven { url 'https://jitpack.io' }
    }
}

Step 2. Add the dependency

dependencies {
	implementation 'com.github.alexnix:voyager-server-spring-boot-starter:
   
    '
   
}

may be a commit hash, for example 63d7ee5

Maven

Step 1. Add the JitPack repository to your build file


   
    
    
        
     
      jitpack.io
     
        
     
      https://jitpack.io
     
    
    

   

Step 2. Add the dependency


   
    
    
     com.github.alexnix
    
    
    
     voyager-server-spring-boot-starter
    
    
    
     VERSION
    

   

may be a commit hash, for example 63d7ee5

How to use

Step 1. Create a model that extends HasId

Kotlin

@Entity
@Table(name="books")
data class Book(
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    override var id: Long = 0,
    
    val title:String,
    
    val author:String
): HasId

Java

@Entity
@Table(name = "books")
public class Book implements HasId {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Long id;

    public String title;

    public String author;

    @Override
    public long getId() {
        return id;
    }

    @Override
    public void setId(long id) {
        this.id = id;
    }
    
    ... the rest of the getters and setters ...
}

Step 2. Create a repository that extends a VoyagerRepository (for example VoyagerRepositoryJPA)

Kotlin

interface BookRepo: VoyagerRepositoryJPA<Book>

Java

public interface BookRepo extends VoyagerRepositoryJPA<Book> {
}

Step 3. Create a service that extends a VoyagerService (for example VoyagerServiceJPA)

Kotlin

@Service
class BookService(private val repo: BookRepo): VoyagerServiceJPA
   (repo)
  

Java

@Service
public class BookService extends VoyagerServiceJPA<Book> {
    public BookService(@NotNull VoyagerRepositoryJPA<Book> repo) {
        super(repo);
    }
}

Step 4. Create a controller that extends VoyagerController

Kotlin

(r)">
@RestController
@RequestMapping("/books")
class BookCtrl(r: BookService): VoyagerController
   (r)
  

Java

{ public BookCtrl(@NotNull BookService service) { super(service, new DefaultACL<>(), new DefaultHooks<>()); } }">
@RestController
@RequestMapping("/books")
public class BookCtrl extends VoyagerController<Book, BookService> {
    public BookCtrl(@NotNull BookService service) {
        super(service, new DefaultACL<>(), new DefaultHooks<>());
    }
}

ACLs

ACL is a way to enforce access permission for the create/read/update/delete operations. To do so, there are two options:

  • provide a custom ACL object (extends ACL) in the controller constructor, or
  • override the corresponding functions in the controller

The following code snippet prohibits any delete operations:

Kotlin

override fun deleteAcl(item: Book) = false

Java

@Override
public boolean deleteAcl(@NotNull Book item) {
	return false;
}

Complex permission logic can be implemented inside those methods, by looking at the current user object (obtained from spring-security) and at the object being changed. For example to restrict deleting of objects, just the their owner of the an administrator. Such logic would look like:

override fun deleteAcl(item: Book) = currentUser.roles.includes("admin") || currentUser.id == book.owner_id

Hooks

Hooks provide a way to react to events before and after they happen. Note, that hooks cannot enforce permissions (ACLs should be used for this) but the beforeReadMany hook provides a way to mutate the query filters, so this can, for example, restrict a uses from reading all entities, with the exception of his own, by programmatically adding a filter such as: owner_id=eq: .

Same as ACLs, hooks can be implemented in two different options:

  • provide a custom Hooks object (extends Hooks) in the controller constructor, or
  • override the corresponding functions in the controller

Additionally, whatever the after hooks return will be returned in the HTTP response. So this functionality can be used to send responses that deviate from the classic REST responses.

Such responses are marked with the __voyager_api JSON key and must follow the following schema:

{
	__voyager_api: true,
	post?: Object[],
	put?: Object[],
	delete?: Object[],
}

This is useful for informing the client of side effects, in response to an event, for example creating a restaurant review will create (post) the review object and will update (put) the restaurant object, by adjusting its rating. In this scenario, the VoyagerResponse object will have the appropriate values in the post and put fields.

The following table describes typical use cases for each hook. Where empty, there was not a clear use case for them, but where added for symmetry.

Create Read Many Read One Update Delete
Before Add server generated fields, such as owner id or createdAt Add filters (query where clauses), for example to restrict the query only to entities where owner_id == user_id
After Create/update/delete side effect entities and return them in a VoyagerResponse object Populate foreign keys fields with the actual objects Create/update/delete side effect entities and return them in a VoyagerResponse object Create/update/delete side effect entities and return them in a VoyagerResponse object

Demo Projects

  • Java
  • Kotlin [coming soon]
You might also like...
An application that simulate the Swedish Transport Agency, implemented with Spring Boot, Kotlin and GraphQL

graphql-kotlin-spring-server An application that simulate the Swedish Transport Agency, implemented with Spring Boot, Kotlin and GraphQL Running the s

API for a library using Kotlin, Spring-boot and covered by test

Library API This API is to create Books and be able to borrow from them I'm using: Spring Boot version 2.5.6 Kotlin 1.5.31 Java 11 I'm implementing us

Push notification application using One Signal + Spring Boot + Kotlin

Spring Boot push notification system using One Signal This project was created to demonstrate a simple application built with Kotlin + Spring Boot inc

Kotlin Based Spring Boot ETL project
Kotlin Based Spring Boot ETL project

Adverity ETL REST API (AERA) A simple ETL Spring Boot application with H2. This API provides the following basics functionalities: Endpoint that retur

Spring Boot Webflux RDBMS Sample App

R2DBC Spring Boot Webflux Sample Project generate schema (DDL script) h2-console (Web based database management console) WebFlux and r2dbc is not supp

Solution for task 5 on Spring Boot https://t.me/try2py/197

IouRestService (Spring Boot Application) Решение задачи 5 https://t.me/try2py/197 Условие задачи: Четверо соседей по комнате имеют привычку занимать д

GraphQL for Java with Spring Boot made easy.

GraphQL for Java with Spring Boot made easy.

API Rest With Kotlin And Spring Boot

##API REST WITH KOTLIN AND SPRING BOOT GET Url: http://localhost:8080/customers Response (Status Code: 200 Ok) { "_embedded": { "customer

Créer un microservice avec Spring Boot et Kotlin
Créer un microservice avec Spring Boot et Kotlin

🚀 Créer un microservice avec Spring Boot et Kotlin Ce dépôt contient les slides et la démo du talk "créer un microservice avec Spring Boot et Kotlin"

Owner
Alexandru Niculae
Alexandru Niculae
This repository contains RabbitMQ Protobuf starters with its usage samples for spring-rabbit and spring-cloud-starter-stream-rabbit modules

This repository contains RabbitMQ Protobuf starters with its usage samples for spring-rabbit and spring-cloud-starter-stream-rabbit modules

Maksim Kostromin 2 Nov 29, 2021
Spring-with-maven - Spring Boot App with Postgresql and maven

Spring Boot Api Aplikasi ini dibuat menggunakan bahasa kotlin dan untuk database

Aldi Aulia Rosyad 1 Jan 12, 2022
The Okila server project uses the Spring boot framework and uses the Kotlin language

Okila-Server The Okila server project uses the Spring boot framework and uses the Kotlin language Format Response //The response successfully format

Nankai 1 Oct 25, 2021
Spring boot admin server for android

spring-boot-admin-server 어드민 서버 그래들 implementation("org.springframework.boot:spring-boot-starter-security:2.5.6") // https://mvnrepository.com/artifac

null 1 Nov 16, 2021
Spring-graphql-getting-started - Spring for GraphQL provides support for Spring applications built on GraphQL Java

Getting Started with GraphQL and Spring Boot Spring for GraphQL provides support

Shinya 0 Feb 2, 2022
Spring Boot Example with Kotlin and Domain Driven Design

Spring Boot Kotlin Domain Driven Design Example Just an example project where ddd is implemented with some other great patterns and architecture from

Fernando Guevara Sanchez 16 Jun 29, 2022
A sample skeleton backend app built using Spring Boot kotlin, Expedia Kotlin Graphql, Reactive Web that can be deployed to Google App Engine Flexible environmennt

spring-kotlin-gql-gae This is a sample skeleton of a backend app that was built using: Spring Boot(Kotlin) Reactive Web Sprinng Data R2DBC with MYSQL

Dario Mungoi 7 Sep 17, 2022
Sample Social Login Project of Spring Boot and Kotlin

Sample-Spring-Boot-Social-Kotlin Sample Social Login Project of Spring Boot and Kotlin dependencies dependencies { implementation("org.springframewor

Seokhyun 2 Oct 11, 2021
This repository demonstrates how Kotlin can simplify Spring Boot configuration properties file mapping

Kotlin spring-boot nested config props This repository demonstrates how Kotlin can simplify Spring Boot configuration properties file mapping @Constru

Maksim Kostromin 1 Oct 11, 2021
My personal template for a Spring Boot REST reactive webapp

My personal spring boot kotlin reactive template Features Spring Security implementation with JWT access and refresh token MongoDB database Project Co

Dušan 2 Dec 1, 2021