This release brings many incremental improvements and some long overdue architecture cleanups.
Make sure to familiarize yourself with the updated UrlMapper behavior and QueryParams implementation.
Any application following the convention recommended the past year should not have any issues with this.
Early support for faceted search
Faceted search is used by many UIs to allow users to quickly navigate data sets. For example, virtually every online shop makes
use of this feature to show product categories and the number of products in that category. Those categories, denoted as
facets, have a label, a set of values and a count for each value. Facets may also depend on each other, whereas later facets are filtered by former ones.
With FacetModule Crnk provides an out-of-the-box solution to implemented faceted search. For more information have a
look at the new chapter in the documentation.
Documentation updates
The outline of the documentation has been revised. Some of the chapters have been restructured.
And there is now a cheatsheet giving an overview
of the most important features and APIs.
The crnk-examples have been renamed to crnk-integration-examples to clearly distinguish from the main
crnk-example application. The name change reflects the fact that those examples are only meant to showcase
the integration of Crnk into various frameworks, not its entire feature set.
New UrlMapper default configuration
The DefaultQuerySpecUrlMapper implementation offers a enforceDotPathSeparator property that
has historically been disabled to maintain backward compatibility. It allows to write filter parameter as either:
filter[person][address][city]=Zurich
filter[address][city]=Zurich
or
filter[person][address.city]=Zurich
filter[address.city]=Zurich
Hereby person is the resource type and address.city a nested attribute. With the first notation,
issues can arise if resources and relationships carry the same name. This ambiguity prevents Crnk from
properly resolving paths and may lead to hard to understand errors. For this reason Crnk has recommended
the second flavor for some time while at the same time offering backward compatibility with the first one.
Setting enforceDotPathSeparator to true removes support for the first notation, meaning Crnk will only support
the second notation and will always be able to properly resolve paths. If this causes issue for your applicaiton,
the flag can easily be disabled again, for example, in SpringBoot the flag is accessible
with the crnk.enforceDotPathSeparator property.
Simplified QuerySpec with new PathSpec
All QuerySpec-related objects like FilterSpec and SortSpec now hold the attribute path
as PathSpec. PathSpec facilitate working with paths compared to the previous List<String> solution.
It offers various methods create new instances and can be used to quickly construct filter and sort
specifications.
Relationships loading handled according to JSON API specification
The specification from http://jsonapi.org/format/#fetching-relationships
mandates two relationship links:
With this release, Crnk properly handles GET request of self links by no longer returning the entire resources, but only the type and id:
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json
{
"links": {
"self": "/articles/1/relationships/author",
"related": "/articles/1/author"
},
"data": {
"type": "people",
"id": "12"
}
Behind the scenes, the same relationship repository implementation is called. The QuerySpec will specify that only the identifier is required through
the includedFields property.
QuerySpecVisitor
The new QuerySpecVisitor and QuerySpecVisitorBase classes allow to visit
a QuerySpec by calling QuerySpec.accept(QuerySpecVisitor). Visitors can be used, for example,
to easily modify attribute paths within a QuerySpc.
Removal of deprecated Repository annotations
The annotation-based repositories have been deprecated since Crnk 0.x and have now been removed. A switch to the Interface-based repositories like
ResourceRepositoryV2 is quickly implemented if somewhere still necessary.
Optimized QueryParams code base
QueryParams has been deprecated since Crnk 0.x. So far both QuerySpec and QueryParams have been first-class citizens within Crnk. With this release, support
for QueryParams has been refactored and remains support through the QuerySpec-to-QueryParams conversion process. That has been the recommended and
only meaningful setup for a long time. The big benefit is a much lighter and more robust code base in the area.
Future release either drop QueryParams support or move it out into a dedicated module. Contributes in the area would
be welcomed. If it is no longer deemed useful
by anybody, it will be removed sometime in Q1/Q2 2019.
Classpath scanning for Typescript generator
The Typescript generator used to need a running application to extract information about the set
of resources and repositories. This remains the best and only way to reliably extract all information
out of a Crnk-based application. However, due to this architecture, generation is also prone to quickly fail
in case of misconfiguration of the application. For this reason, this release introduces an new, alternative
mechanism where the classpath can be scanned for @JsonApiResource-annotated classes and repository interface
definitions extending ResourceRepositoryV2. The benefit is a simpler setup at the cost of potentially
missing out on non-standard repositories that are not backed by a @JsonApiResource annotation.
In Gradle this then looks like:
dependencies {
typescriptGenRuntime project(':management:management-api')
...
}
typescriptGen{
resourcePackages = ['îo.crnk.example']
runtime {
configuration = 'typescriptGenRuntime'
}
...
}
new property: crnk.enforceIdName
If set to true, it will name all `@JsonApiId` annotated fields as `id` on the rest layer (sorting, filtering, etc.) regardless of its Java name.
By default this is not enabled for historic reasons. But enabling it more closely reflects the JSON API specification and is recommended to do so.
It likely will be enabled in Crnk 3 by default.
@JpaResource annotation deprecated
@JpaResource rather than @JsonApiResource has historically been necessary to modify the naming
of Entity-based resources. This is no longer necessary and @JsonApiResource can be used together
with classes annotated with @Entity.
Historic Activiti repositories
There is initial experimental support for historic resource repositories of Activiti tasks and processes.
ActivitiModuleConfig config = new ActivitiModuleConfig();
ProcessInstanceConfig processConfig = config.addProcessInstance(ScheduleApprovalProcessInstance.class);
processConfig.historic(HistoricScheduleApprovalProcessInstance.class);
TaskRepositoryConfig taskConfig = config.addTask(ApproveTask.class);
taskConfig.historic(HistoricApproveTask.class);
taskConfig.filterBy("description", ENFORCED_DESCRIPTION);
return ActivitiModule.create(processEngine, config);
Bidirectional Object to String mapping with TypeParser
The TypeParser class of Crnk has been extended to not only parse Strings, but also map objects back to Strings.
Most notably, the DefaultQuerySpecUrlMapper makes use of this functionality to represent filter values
as Strings in urls. Thereby, the extensibility of the TypeParser allows to customize that mapping.
Simplified customizations of Criteria-based crnk-data-jpa repositories
There is a new interface JpaCriteriaRepositoryFilter and base class JpaCriteriaRepositoryFilterBase that allow
easy customization of CriteriaQuery objects. The interfaces are a specialization of JpaRepositoryFilter
and can be used in the same manner by registering it to the JpaModuleConfig.
InMemoryEvaluator
InMemoryEvaluator gained a new constructor that takes a ResourceRegistry. This allows the use of resource information
when accessing resources. This allows its use with more customized resources and relationships, like the use of
@JsonApiRelationId and custom ResourceFieldAccessors instead of just basic plain Java beans. Note that QuerySpec.apply(...)
does not have access to a ResourceRegistry and, consequently, continues to use the traditional behavior.
Logging in crnk-meta
Various logging statements have been reduced to level TRACE to make the general DEBUG log level of io.crnk a bit less noisy.
@JsonApiRelationId supported by crnk-validation
Validation errors on relationship identifiers annotated with @JsonApiRelationId now correctly carry the relationship name (without the
typical "id" suffix) in the JSON API error.
Simplified BulkRelationshipRepositoryV2
The BulkRelationshipRepositoryV2 interface implements two default methods that allow the implementation of a single findTargets method.
A future V3 version of the interface will likely move this into crnk-core to keep the interface this simple without having to rely
on default methods.
simplified crnk-data-jpa setup in Spring Boot
The exposeAll behavior automatically backs-off if a repository is registered manually. Setting the properly to false is no longer necessary.
Early security checks for bulk operations
The operations module now checks any bulk operations against configured configured role-based authorization rules (SecurityModule) and other ResourceFilter.
It allows to catch security violations early before accessing any repositories.