Crnk Spring Boot example
Crnk is a native resource-oriented rest library where resources and relationships are first class citizens and not just path mappings on methods. Model your application as resources and relationships and implement the repositories to access them. This simplifies development and opens up many, powerful new possibilities:
Fully transparent, automated HATEOAS setup.
Fetch complex object graphs with the inclusion of relationships to perform well even with mobile connections.
Let your API evolve with the introduction of new attributes and relationship and have it discoverable. Stop handing out RPC-style APIs where every further added, isolated service makes the system less understandable.
Prerequites
- [Spring Boot - https://spring.io/projects/spring-boot](https://spring.io/projects/spring-boot)
Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can "just run".
See [Spring | Spring Quickstart Guide - https://spring.io/quickstart](https://spring.io/quickstart) to learn more.
Example
The following gives a brief example of how to setup Crnk with Spring Boot.
See crnk-framework/crnk-integration-examples/spring-boot-minimal-example at master · crnk-project/crnk-framework - https://github.com/crnk-project/crnk-framework/tree/master/crnk-integration-examples/spring-boot-minimal-example to learn more.
build.gradle
Add Crank dependencies to bundle.gradle
.
Remember to make org.springframework.boot
and org.springframework.boot:spring-boot-dependencies
have the same version.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 // build.gradle plugins { id 'org.springframework.boot' version '2.6.2' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'java' id 'org.springframework.experimental.aot' version '0.11.1' } group = 'com.cloudolife.common.configuration.service' version = '0.0.1-SNAPSHOT' sourceCompatibility = '17' configurations { compileOnly { extendsFrom annotationProcessor } } repositories { maven { url 'https://repo.spring.io/release' } mavenCentral() + jcenter() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-web' developmentOnly 'org.springframework.boot:spring-boot-devtools' testImplementation 'org.springframework.boot:spring-boot-starter-test' + implementation 'io.crnk:crnk-setup-spring-boot2' + implementation 'io.crnk:crnk-format-plain-json' + implementation 'io.crnk:crnk-home' + + implementation 'org.junit.jupiter:junit-jupiter-api:5.5.1' } test { useJUnitPlatform() } + bootBuildImage { + builder = 'paketobuildpacks/builder:tiny' + environment = ['BP_NATIVE_IMAGE': 'true'] + } + + dependencyManagement { + imports { + mavenBom 'org.springframework.boot:spring-boot-dependencies:2.6.2' + mavenBom "io.crnk:crnk-bom:3.4.20210509072026" + } + }
JsonApiResource - Project.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 package io.crnk.example.springboot.microservice;import com.fasterxml.jackson.annotation.JsonProperty;import io.crnk.core.resource.annotations.JsonApiId;import io.crnk.core.resource.annotations.JsonApiResource;@JsonApiResource(type = "projects") public class Project { @JsonApiId private Long id; @JsonProperty private String name; public Project () { } public Project (Long id, String name) { this .id = id; this .name = name; } public Long getId () { return id; } public void setId (Long id) { this .id = id; } public String getName () { return name; } public void setName (String name) { this .name = name; } }
Repository - ProjectRepositoryImpl
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 package io.crnk.example.springboot.microservice;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;import java.util.concurrent.atomic.AtomicLong;@Component public class ProjectRepositoryImpl extends ResourceRepositoryBase <Project, Long> { private static final AtomicLong ID_GENERATOR = new AtomicLong (124 ); private Map<Long, Project> projects = new HashMap <>(); public ProjectRepositoryImpl () { super (Project.class); } @Override public synchronized void delete (Long id) { projects.remove(id); } @Override public synchronized <S extends Project > S save (S project) { if (project.getId() == null ) { project.setId(ID_GENERATOR.getAndIncrement()); } projects.put(project.getId(), project); return project; } @Override public synchronized ResourceList<Project> findAll (QuerySpec querySpec) { return querySpec.apply(projects.values()); } }
SpringBootApplication - MinimalSpringBootApplication.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package io.crnk.example.springboot.microservice;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Import;@Configuration @SpringBootApplication @Import({TestDataLoader.class}) public class MinimalSpringBootApplication { public static void main (String[] args) { SpringApplication.run(MinimalSpringBootApplication.class, args); System.out.println("visit http://127.0.0.1:8080/ in your browser" ); } }
Run
Run with Gradle:
1 $ gradlew :crnk-integration-examples:spring-boot-minimal-example:run
The service will be available at http://localhost:8080/
FAQs
java.util.Map io.crnk.spring.setup.boot.mvc.CrnkErrorController.getErrorAttributes(javax.servlet.http.HttpServletRequest, boolean)
Crnk error handling is not compatible with Spring Boot 2.5+.
1 2 3 4 5 // ColCommonConfigurationServiceJavaApplication.java - //@SpringBootApplication + @SpringBootApplication(exclude = {io.crnk.spring.setup.boot.mvc.CrnkErrorControllerAutoConfiguration.class}) public class ColCommonConfigurationServiceJavaApplication {
See Crnk error handling is not compatible with Spring Boot 2.5 · Issue #816 · crnk-project/crnk-framework - https://github.com/crnk-project/crnk-framework/issues/816 to learn more.
References
[1] Crnk: Resource-oriented Rest Development with JSON:API - http://www.crnk.io/
[2] crnk-framework/crnk-integration-examples/spring-boot-minimal-example at master · crnk-project/crnk-framework - https://github.com/crnk-project/crnk-framework/tree/master/crnk-integration-examples/spring-boot-minimal-example
[3] crnk-framework/crnk-integration-examples at master · crnk-project/crnk-framework - https://github.com/crnk-project/crnk-framework/tree/master/crnk-integration-examples
[4] Crnk Documentation - http://www.crnk.io/releases/stable/documentation/
[5] JSON:API — Latest Specification (v1.0) - https://jsonapi.org/format/
[6] JSON:API — Recommendations - https://jsonapi.org/recommendations/
[7] Spring Boot - https://spring.io/projects/spring-boot
[8] Spring | Spring Quickstart Guide - https://spring.io/quickstart
[9] 3.7. Integration with Spring and Spring Boot | Crnk Documentation - http://www.crnk.io/releases/stable/documentation/#_integration_with_spring_and_spring_boot