Hawaii Starters

TODO.

hawaii-starter

TODO.

hawaii-starter-logging

The hawaii-starter-logging delivers a fully configured set of filters that are added to the filter chain in the configured order. The starter contains a default configuration, which can be overridden by adding properties to your configuration. The default configuration consists of the filters listed in the table below.

Filters with a negative order are added to the filter chain before any filters that modify or wrap the request and/or response. The UserDetailsFilter depends on Spring Security (it logs the authenticated Principal) and therefor has a higher order.

Table 1. Default filter configuration
Filter Enabled Order Additional properties

kibana-log

true

-108

  • http-header: the header that contains the client ip address. Defaults to X-Hawaii-Frontend-IP-Address. If no such header is present, the filter uses the remote address from the request.

kibana-log-cleanup

true

-110

-

request-duration

true

-109

-

request-id

true

-106

  • http-header: the response header to which the request id will be writen. Defaults to X-Hawaii-Request-Id.

request-response

true

-105

  • fallbackToFile: write the response to a file if its size exceeds maxLogSize, default value is true

  • directory: the directory where files are written to, defaults to /tmp

  • maxLogSize: the maximum log size to write to the log, see fallbackToFile, default value is 50k

  • allowedContentTypes: For console logging, the allowed content types, empty means allow all. Default value:

    • application/json

    • text/plain

    • text/xml

transaction-id:

true

-107

  • http-header: the request header name that may contain an incoming transaction id, and the response header to which the transaction id is written. Defaults to X-Hawaii-Tx-Id`.

user-details

true

110

-

An example of the default configuration is available in the appendix.

How to use

In order to use Hawaii logging, you’ll need to define an appender that uses the KibanaLogEventEncoder, for example:

    <appender name="kibana" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>log/idm-kibana.log</file>
        <encoder class="org.hawaiiframework.logging.logback.KibanaLogEventEncoder"/>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${tomcat_logs}/hawaii-idm.log.%d{yyyy-MM-dd}.gz</fileNamePattern>
            <maxHistory>10</maxHistory>
        </rollingPolicy>
    </appender>

hawaii-starter-rest

TODO.

hawaii-starter-test

TODO.

hawaii-starter-async

The asynchronous request execution in Hawaii is built on top of the scheduling in Spring Framework, see the Spring documentation for a baseline explanation.

There are two main additions:

  • More flexibility in executor configuration

  • Task timeout

Executor configuration

The Hawaii async configuration allows the definition of executors. An executor can be viewed as a thread pool. An executor configuration looks something like this:

executors:
-
    name: default
    corePoolSize: 10
    keepAliveTime: 60
    maxPendingRequests: 60
    maxPoolSize: 60

The lowest level of configuration is a task. Tasks are grouped into systems. A system could be some backend system against which requests are executed, or a database on which queries are executed. Each request or query represents a task in Hawaii async terminology. System and task configuration looks like this:

systems:
  -
      name: mySystem
      defaultExecutor: myExecutor
      defaultTimeout: 3
      tasks:
        -
            method: myTask
            executor: mySpecialExecutor
            timeout: 1
        -
            method: myOtherTask

As can be seen, an executor can be assigned on system level. This will be the default executor for all the tasks in the system, unless a specific executor is configured for a task, such as myTask in the example. The same mechanism applies to the timeout settings. It is therefore perfectly legal to configure a task without any properties. However, it remains necessary to define the task in the configuration, otherwise it can’t be used, i.e. every task must be defined in the configuration.

Finally, there are some global properties:

defaultExecutor: default
defaultTimeout: 10
asyncTimeoutExecutorPoolSize: 10

These define the default executor and timeout. These defaults will be used if no executor or timeout is defined on either task or system.

The asyncTimeoutExecutorPoolSize property defines the number of threads that are used to run timeout tasks. See task timeout.

Task timeout

Another addition is automatically timing out tasks. For each task that is executed, the Hawaii async framework enqueues a cancellation task into a separate executor. If the timeout moment arrives, the timeout task is executed and will attempt to abort the actual task being executed. The actual task will remove the timeout task when it finishes, so if a task runs within its time limit, the timeout task will never be run.

Usage

In practice, using the Hawaii asynchronous framework is not that different from using Spring’s: asynchronous execution must be enabled with @EnableAsync and methods that are to be executed asynchronously must be annotated with the @Async annotation, and they must have a Future typed return value.

Additionally, an asynchronous configuration must be defined in the file identified by the hawaii.async.configuration property, which is set to ./config/async-config.yml by default.

The essential difference in usage is that where Spring allows the specification of an executor by specifying the value of the @Async annotation, the Hawaii additions require specifying the Task name instead of the executor. The Hawaii async configuration will take care of routing the execution to the correct Executor.

HTTP

To execute http requests using the Hawaii async framework, you’ll need to use the HawaiiHttpComponentsClientHttpRequestFactory to enable timing out of tasks that run too long.

You can use the LoggingClientHttpRequestInterceptor to log requests and responses made over http. Note that since this interceptor consumes the response, this will only work if you wrap the HawaiiHttpComponentsClientHttpRequestFactory in a org.springframework.http.client.BufferingClientHttpRequestFactory, or take other measures to make sure the response can be read more than once.

Components

The following diagram shows the various components in the Hawaii async solution:

hawaii async task overview

In the diagram, MethodX is the call that must be executed asynchronously, for example service or repository method. The @Async annotation causes Spring to create a proxy around this method. The proxy locates the executor, which in the Hawaii case is a DelegatingExecutor which will delegate to the real executor specified for the task. The executor takes the MethodX Runnable and executes it on an available thread.

Additionally, a delayed (by the configured timeout) task, the MethodX Guard is created and passed to the Delayed Guard Executor.

Both tasks share the Shared Task Context which allows them to share logging context, and which also provides access for the guarded task to remove the guard task upon completion, and for the guard task to abort the guarded task upon activation.

Processing

The sequence below shows the components working together to execute a task.

hawaii async task overview normal

The sequence below shows the flow when a task times out.

hawaii async task overview timeout