Skip to content

Core

Module core

This module holds utilities used in other libraries of the toolkit. Check the packages' documentation for more details. You can find a quick recap of the main features in the sections below.

Install the Dependency

This module is not meant to be imported directly. It will be included by using any other part of the toolkit. However, if you only want to use the utilities, logging, etc. (i.e., for a desktop application), you can import it with the following code:

1
2
3
4
5
repositories {
    mavenCentral()
}

implementation("com.hexagonkt:core:$hexagonVersion")
1
2
3
4
5
<dependency>
  <groupId>com.hexagonkt</groupId>
  <artifactId>core</artifactId>
  <version>$hexagonVersion</version>
</dependency>

Package com.hexagonkt.core

JVM information and other useful utilities.

Classpath URLs in native images

To use the 'classpath' URL scheme on GraalVM native images, the native-image command requires to add the Classpath handler manually with the --enable-url-protocols=classpath parameter.

Flags (System Properties)

  • DISABLE_CHECKS: set to true to disable some checks in order to shave a few ms. in production. Do not enable it in application development and turn it on only when the application is extensively tested.

Package com.hexagonkt.core.converters

Registry of functions to convert from one type to another.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// Define a mapper from a source type to a target type
ConvertersManager.register(Date::class to String::class) { it.toString() }

// Conversions can be done with different utility methods
val directConversion = ConvertersManager.convert(Date(), String::class)
val utilityConversion = Date().convert(String::class)
val reifiedUtilityConversion = Date().convert<String>()

assertEquals(directConversion, utilityConversion)
assertEquals(utilityConversion, reifiedUtilityConversion)

// Conversion mappers can be deleted
ConvertersManager.remove(Date::class to String::class)

// Trying to perform a conversion that has not a registered mapper fails with an error
val e = assertFailsWith<IllegalStateException> { Date().convert<String>() }
val source = Date::class.simpleName
val target = String::class.simpleName
assertEquals("No converter for $source -> $target", e.message)

Package com.hexagonkt.core.handlers

Provide general utilities to attach many handlers to be applied on events processing. Events can be of any type.

Handlers may or may not be applied to certain events at runtime based on rules provided as a predicate (function).

If an event doesn't match a handler's predicate, that handler is ignored, and the next one will be processed.

When a handler's predicate returns true, its callback will be called. That block will process the event, and return a modified copy with the changes.

The callback block will decide if subsequent handler's will be evaluated by calling the next handler explicitly (if next method is not called, the handlers defined later won't be evaluated).

There are types of handlers like 'After' y 'Before' that call next as part as their operation discharging the user of doing so.

The events are passed to handlers' callbacks wrapped in a 'context'. The context can also pass information among handlers in the attributes field. And store an exception if it is thrown in a previous handler processing.

Concepts:

  • Events
    • Context
  • Handlers
    • Predicates
    • Callbacks

Types of handlers:

  • On Handler: the callback is executed before calling the remaining handlers. next is called after the callback.
  • After Handler: the predicate is evaluated after the remaining handlers return, and the callback is executed after. next is called before the callback
  • Filter Handler: next is not called by this handler, its callback is responsible for doing so if needed.
  • Chain Handler: this handler contains a list of handlers inside.

IMPORTANT: the order is NOT the order, it is the depth. Handlers are not linked, they are NESTED. The next() method passes control to the next level.

This definition:

1
2
3
H1
H2
H3

Is really this execution:

1
2
3
4
5
H1 (on)
  H2 (on)
    H3 (on)
  H2 (after)
H1 (after)

Package com.hexagonkt.core.logging

Provides a logging management capabilities abstracting the application from logging libraries.

The following code block shows the most common use cases for the Logger class:

 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
val classLogger: Logger = Logger(Runtime::class) // Logger for the `Runtime` class
val instanceLogger: Logger = Logger(this::class) // Logger for this instance's class

logger.info {
    """
    You can add a quick log without declaring a Logger with 'com.hexagonkt.helpers.logger'.
    It is a default logger created for the System class (same as `Logger(System::class)`).
    """
}

classLogger.trace { "Message only evaluated if trace enabled at ${Jvm.id}" }
classLogger.debug { "Message only evaluated if debug enabled at ${Jvm.id}" }
classLogger.warn { "Message only evaluated if warn enabled at ${Jvm.id}" }
classLogger.info { "Message only evaluated if info enabled at ${Jvm.id}" }

val exception = IllegalStateException("Exception")
classLogger.warn(exception) { "Warning with exception" }
classLogger.error(exception) { "Error message with exception" }
classLogger.warn(exception)
classLogger.error(exception)
classLogger.error { "Error without an exception" }

classLogger.time("Logs the time used to run the following block of code") {
    val message = "Block of code to be timed"
    assert(message.isNotBlank())
}

instanceLogger.flare { "Prints a log that stands out for ease searching" }

// Logging level can be changed programmatically
LoggingManager.setLoggerLevel(ERROR)
LoggingManager.setLoggerLevel(classLogger, DEBUG)
LoggingManager.setLoggerLevel("com.hexagonkt", INFO)

By default, Hexagon uses the Java Util Logging logging library, you can use any of its implementations by just adding another logging adapter as a dependency. Below you can see some alternatives:

Package com.hexagonkt.core.logging.jul

Logging implementation for Java logging module. This is the default implementation.

Package com.hexagonkt.core.media

Media types definitions and constants for default media types.

Package com.hexagonkt.core.security

Cryptography and key stores utilities.