Kotlin Kandy: Getting The Indices Of A Collection
Kotlin adds a lot of useful extensions to the collection classes. One of them is the indices property. The indices property returns the indices of the elements in the collection as an IntRange.
My name is Hubert A. Klein Ikkink also known as mrhaki. I work at the great IT company JDriven. Here I work on projects with Java, Groovy, Gradle, Asciidoctor and more. At JDriven we focus on enterprise technologies. All colleagues support craftsmanship and are very eager to learn new technologies. This is truly a great environment to work in.
Kotlin adds a lot of useful extensions to the collection classes. One of them is the indices property. The indices property returns the indices of the elements in the collection as an IntRange.
The JVM Test Suite plugin is part of the Java plugin and provides a nice way to configure multiple test types in our build file. Even if we don’t have multiple test types we have a default test type, which is used when we run the Gradle test task. Using the test suite DSL we can configure the task of type Test that belongs to a test suite type. The current release of the JVM Test Suite plugin provides a single target for a test suite type with a single Test task. This will probably change in future releases of the plugin so more task of type Test can be created and configured.
The version catalog in Gradle is very useful to have one place in our project to define our project and plugin dependencies with their versions. But we can also use it to define our project version and then refer to that version from the version catalog in our build script file. That way the version catalog is our one place to look for everything related to a version. In the version catalog we have a versions section and there we can define a key with a version value. The name of the key could be our project or application name for example. We can use type safe accessors generated by Gradle in our build script to refer to that version.
The JVM Test Suite plugin adds an extension to our build that allows us to configure test tasks. We always can access the default test task and for example specify the test framework we want to use. Gradle will then automatically add the dependencies of that test framework to the testImplementation configuration. If we want to add more dependencies to the testImplementation configuration we don’t have to do that by explicitly mentioning the testImplementation configuration. Instead we can also use a dependencies block from within the JvmTestSuite extension. Any extra dependencies we need to run our tests can be added using the configuration names without a test prefix. Gradle will automatically add them to the correct test configuration for us so the dependencies are available when we compile and run our tests. This will also work for any other new test type we add to the test suites, e.g. for integration tests.
In a previous post we learned we can turn a string into a string with kebab casing using dasherize from the dw::core::Strings module. If we want to turn a string into a string with camel casing we can use the underscore function. The underscore function will replace spaces, dashes and camel-casing with underscores, which makes the result snake-casing. Any uppercase characters are transformed to lowercase characters.
When running Keycloak it can be useful to log events like a login or logout event using the jboss-logging event listener. This is a built-in event listener that will use JBoss logging to log events. For example we can configure our JBoss logging to log to the standard output streams and when we run Keycloak we can see in the console output details about events when they happen. The event listener jboss-logging is enabled by default for a realm. We can check it from the Events Config page where it is listed in the Event Listeners field.
Spock is an awesome test framework for testing our Java or Groovy code. Spock itself is written with Groovy and provides a nice syntax to define our tests, or specifications in Spock terminology. To configure support for using Spock in our Gradle build is very easy with the JVM Test Suite plugin (included with the Java plugin). The plugin gives us a nice syntax to define different types of tests, for example integration tests, with their own source set, dependencies and configuration. To use Spock as testing framework we only have to use the method useSpock within a test configuration. The default version of Spock that is used is 2.1-groovy-3.0 when we use Gradle 7.6. If we want to use another version we can use a String parameter when we use the useSpock method with the version we want to use.
Since Gradle 7.3 we can use the JVM Test Suite plugin to define in a declarative way tests for our build. For example adding integration tests with a new source set and dependencies becomes easier with this plugin. The plugin is automatically part of the Java plugin so we don’t have to define it explicitly in our build. Configuring the default test task can also be done using the syntax of the JVM TestSuite plugin. We can use several methods from the JvmTestSuite class in our configuration. For example if we want to use Spock as testing framework we can simply add the method useSpock in our build script. Or if we want to use the JUnit 5 Jupiter engine we can use useJUnitJupiter. These methods will add dependencies in the testImplementation configuration. There is a default version for the dependencies if we use the method without arguments. But we can also define the version as String argument for these methods. The version catalog for our project is the place to store version for our dependencies, so it would be nice if we could use the version defined in our version catalog as argument for the use<TestFramework> methods. We can reference the version very simple by using libs.versions.<version-key>. This will return the value we defined as version in our version catalog.
The dw::core::Strings module has useful functions for working with string values. One of the functions is dasherize. The function takes a string argument and replaces spaces, underscores and camel-casing into dashes. The resulting string value with hyphens is also called kebab-casing. The dasherize function also turns any uppercase character to lowercase.
When we are working with a multi-module project in Maven we might want to exclude a module when we invoke a build command. We might only be interested in partially building some modules. We can use the command line option -pl or --projects to specify a list of modules that need to be in our build. But we can also use ! followed by the module name to exclude modules from our build.
The version catalog in Gradle is very useful to define a list of dependencies in one single place. In our build script we references dependencies from the version catalog using type safe accessors when we define a dependency for a configuration. Sometimes multiple dependencies belong to each other and are used in combination with each other. In the version catalog we can define bundles of such dependency groups. Instead of referencing each dependency individually we can reference a bundle from the version catalog in our build script. This keeps our build script cleaner and updating a bundle only needs a change in the version catalog.
A version catalog in Gradle is a central place in our project where we can define dependency references with their version or version rules. A dependency reference is defined using an identifier with a corresponding dependency definition containing the coordinates of the dependency. Now we can reference the dependency using the identifier in for example a dependency configuration, e.g. implementation(libs.spring.core). If there is a version change we want to apply we only have to make the change in our version catalog. An added bonus is that Gradle generates type safe accessors for the identifier we use in our version catalog, so we can get code completion in our IntelliJ IDEA when we want to reference a dependency from the version catalog.
Besides dependencies we need to build and test our software we can also include definitions for Gradle plugins including their version.