2.9.20181028143330

Version: 2.9.20181028143330

Documentation (pdf)

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-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-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.