3.1.20191113192440
Version: 3.1.20191113192440
This release provides many incremental improvements to 3.0 while introducing three major new features.OpenAPI Support (experimental)
Experimental support for OpenAPI is now available as extension to the Crnk generator. It will generate an OpenAPI schema out of any Crnk endpoint by inspecting the implementation and derive a schema. An example setup looks like:buildscript { dependencies { classpath "io.crnk:crnk-gen-gradle:${version}" } } apply plugin: 'crnk-gen' crnkGen { runtime { configuration = 'openapiGenRuntime' } // fork generation into new process to have clean environment forked = true // specify the package to look for resources resourcePackages = ['io.crnk.test'] openapi { // enable OpenAPI generation within Gradle plugin enabled = true // specify name of openapi template in the build dir to merge onto templateName = "openapi-template.yml" // specify name of API to display in the generated OpenAPI file projectName = "Generated Title" // specify version of the API to display in the generated OpenAPI file projectVersion = "0.1.0" // specify name of openapi template in the build dir to merge onto projectDescription = "A generated description of the API." // specify location of generated sources genDir = file('src/resources') } } } crnkGen.init()Fore more information see here. Have a look at the GitHub tickets for the future roadmap.
Bulk Repositories (experimental)
There is a new experimental BulkResourceRepository that closely resembles ResourceRepository but takes multiple resources as arguments. This give the repository the possibility to optimize bulk mutations of multiple resources, like sharing a database transaction. Currently only POST is implemented, not PATCH and DELETE yet! More information can be found here. In future releases this will be aligned with support for the upcoming JSON:API 1.1 specification.public class BulkInMemoryRepository implements BulkResourceRepository<Task, Long> { @Override public <S extends T> List<S> create(List<S> resources) { ... } ... }
TestKit
There is a new project io.crnk:crnk-testkit to facilitate testing of JSON:API based endpoints. As first contribution there is aRandomWalkLinkChecker
:
CrnkClient client = ... HttpAdapter httpAdapter = client.getHttpAdapter(); RandomWalkLinkChecker linkChecker = new RandomWalkLinkChecker(httpAdapter); linkChecker.setWalkLength(100); linkChecker.addStartUrl(...) linkChecker.performCheck();It performs a random walk on an API endpoint by following the links as specified by JSON:API. It will verify that each links provides a valid 2xx response code. By having a sufficiently long walk, it will ensure that any GET request can be served with high probability. This in turn allows developers to focus on testing business functionality, while lower layer REST details like linking get verified automatically. More information and roadmap are available here.
Minor Improvements
- There is a new documentation section about in-memory repositories and their use for small data sets, testing and mocking.
-
CrnkClient verifies the resourceClass of passed QuerySpec objects to ensure they match with the invoked
repositories. Watch out for this change, because it was easy to get it wrong and may never got noticed.
The change makes no difference for empty QuerySpecs. But filtering, sorting and paging requests
get ignored with in-proper typing. The following example will now cause an exception:
CrnkClient client = ... ResourceRepository<Task,Long>repository = client.getRepositoryForType(Task.class); repository.findAll(new QuerySpec(Project.class));
- Attributes and relationships can no longer be named
meta
andlinks
to have a clear distinction to the JSON:API data structures. - Sorting for JPA entities with @EmbeddedId has been improved. For details see 603.
-
Self URLs can now be written manually by letting resources hold link objects implementing
SelfLinksInformation. The Crnk engine will no longer interfere if a self link is already
set for a resource or list.
@JsonApiResource(type = "project") public class Project { @JsonApiLinksInformation private DefaultSelfLinksInformation links = new DefaultSelfLinksInformation(); ... }
- @JsonProperty handling is fixed for nested resource. This means the relationships between parent and child can also be renamed.
-
CrnkClient makes use of nested URLs to access nested resources, e.g.
/api/project/{projectId}/tasks/{taskId}
. - @JsonApiField.sortable and @JsonApiField.filterable allow to disable sorting and filtering for a field. A 400 BAD_REQUEST will be returned in case of a violation has been detected. See here.
-
HomeModule will add links to JSON:API responses if there are resources with overlapping paths, such as
/api/tasks
and/api/tasks/history
. - HomeModule supports the same exception response format as any other JSON:API response.
- An example for @JsonAnyGetter and @JsonAnySetter has been added to the example application to showcase the use of more dynamic resources, see PersonEntity
-
DataRoom logging has been refined to log with WARN if access to a resource is prohibited.
HTTP errors continue to make use of
403 FORBIDDEN
. - JPA repositories are aware of @JsonApiRelationId annotations and optimize sorting and filtering accordingly. If the id of a relationship is filtered or sorted, Crnk rather makes direct use of the foreign key rather than joining to the foreign table.
- JPA repositories make use of LEFT join when sorting a column on a related entity. This prevents the resources from getting omitted if they do not have such a related entity.
- Nested repositories can now span multiple levels, such as
/api/project/{projectId}/tasks/{taskId}/items/{itemId}
-
Repositories from CrnkClient make use of
@JsonApiExposed(false)
. It allows there use on the server-side to consume other services without exposing the repositories again. When returning resources obtained from such a repository, they will maintain proper linking to the original service as long a the resources carry a links object implementing SelfLinksInformation. For an example see spring-boot-microservice-example -
CrnkClient can be configured with a custom ObjectMapper using
CrnkClient.setObjectMapper(...)
. - ResourceIdentifier can be used together with @JsonApiRelationId do not only hold the ID, but also the type of the relationship. Useful when inheritance is involved to directly address the proper subtype.
-
ResourceTypeHolder
interfaces allows a resource to hold its resource type. This can proof useful in more dynamic settings where inheritance is involved and a repository likes to manipulate the type of its resources without having to work with strongly-typed resource classes. Together with @JsonAnyGetter and @JsonAnySetter it allows for highly dynamic, non-compile-time repository implementations similar but simpler than the direct use of theResource
class. For information is available in the documentation.