<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Kotlin &#8211; Manuel Bogner&#039;s Blog</title>
	<atom:link href="https://blog.mbo.dev/archives/category/dev/kotlin/feed" rel="self" type="application/rss+xml" />
	<link>https://blog.mbo.dev</link>
	<description>Solutions to everyday IT problems</description>
	<lastBuildDate>Wed, 15 Nov 2023 15:01:22 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://blog.mbo.dev/wp-content/uploads/2022/11/cropped-cropped-mbo-white_opt-32x32.png</url>
	<title>Kotlin &#8211; Manuel Bogner&#039;s Blog</title>
	<link>https://blog.mbo.dev</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>CORS configuration for REST api accessed from browser</title>
		<link>https://blog.mbo.dev/archives/1988</link>
		
		<dc:creator><![CDATA[Manuel Bogner]]></dc:creator>
		<pubDate>Wed, 15 Nov 2023 15:01:19 +0000</pubDate>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Kotlin]]></category>
		<guid isPermaLink="false">https://blog.coffeebeans.at/?p=1988</guid>

					<description><![CDATA[To allow requests against a Spring Boot REST API from a website it is necessary to configure CORS properly. In case you don&#8217;t know your client URLs you can allow all clients by adding a mapping like the following in your Kotlin project: This allows access to all endpoints from all origins via GET, POST [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>To allow requests against a Spring Boot REST API from a website it is necessary to configure CORS properly. In case you don&#8217;t know your client URLs you can allow all clients by adding a mapping like the following in your Kotlin project:</p>



<pre class="wp-block-code"><code>@Configuration
class RestCorsConfig : WebMvcConfigurer {

    override fun addCorsMappings(@NonNull registry: CorsRegistry) {
        registry.addMapping("/**")
            .allowedMethods(HttpMethod.GET.name(), HttpMethod.POST.name(), HttpMethod.DELETE.name())
            .allowedOrigins("*")
    }
}</code></pre>



<p>This allows access to all endpoints from all origins via GET, POST and DELETE methods.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Redis Testcontainer with Kotlin and Spring Boot</title>
		<link>https://blog.mbo.dev/archives/1947</link>
		
		<dc:creator><![CDATA[Manuel Bogner]]></dc:creator>
		<pubDate>Mon, 24 Jul 2023 21:26:56 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Kotlin]]></category>
		<guid isPermaLink="false">https://blog.coffeebeans.at/?p=1947</guid>

					<description><![CDATA[I found lots of samples for creating a redis testcontainer in Spring Boot tests. But none of them really worked. Below is a working base class with a sample. It is based on Spring Boot 3.1.2 and latest testcontainer version at time of writing (&#8220;org.testcontainers:testcontainers:1.18.3&#8221;). The testcontainer-redis versions were avoided on purpose because they were [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>I found lots of samples for creating a redis testcontainer in Spring Boot tests. But none of them really worked. Below is a working base class with a sample. It is based on Spring Boot 3.1.2 and latest testcontainer version at time of writing (&#8220;org.testcontainers:testcontainers:1.18.3&#8221;). The testcontainer-redis versions were avoided on purpose because they were only available with quite old testcontainer version.</p>



<pre class="wp-block-code"><code>import org.junit.jupiter.api.BeforeAll
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.DynamicPropertyRegistry
import org.springframework.test.context.DynamicPropertySource
import org.testcontainers.containers.GenericContainer
import org.testcontainers.containers.wait.strategy.HostPortWaitStrategy

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
abstract class RedisTest {
    companion object {
        private const val REDIS_IMAGE = "redis:7-alpine"
        private const val REDIS_PORT = 6379

        private const val REDIS_CONFIG_HOST = "spring.data.redis.host"
        private const val REDIS_CONFIG_PORT = "spring.data.redis.port"

        private val redisContainer = GenericContainer&lt;Nothing>(REDIS_IMAGE).apply {
            withExposedPorts(REDIS_PORT)
            withReuse(true)
        }

        @JvmStatic
        @BeforeAll
        fun beforeAll() {
            if (!redisContainer.isRunning) {
                redisContainer.start()
                redisContainer.setWaitStrategy(HostPortWaitStrategy())
            }
        }

        @JvmStatic
        @DynamicPropertySource
        fun properties(registry: DynamicPropertyRegistry) {
            registry.add(
                REDIS_CONFIG_HOST,
                redisContainer::getContainerIpAddress
            )
            registry.add(
                REDIS_CONFIG_PORT,
                redisContainer::getFirstMappedPort
            )
        }
    }
}</code></pre>



<p>With this in place you can create a simple test by extending <code>RedisTest</code></p>



<pre class="wp-block-code"><code>import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.CsvSource
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.data.redis.core.RedisTemplate

class EventSourceTest @Autowired constructor(
    val redisTemplate: RedisTemplate&lt;String, String>
) : RedisTest() {

    @ParameterizedTest
    @CsvSource(
        value = &#91;
            "test1, 1",
            "test2, 2",
            "test3, 3",
        ]
    )
    fun redis(
        key: String,
        value: String
    ) {
        redisTemplate.opsForValue().set(
            key,
            value
        )
        assertThat(redisTemplate.opsForValue().getAndDelete(key)).isEqualTo(value)
    }

}</code></pre>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Using Generic Spring Boot Events</title>
		<link>https://blog.mbo.dev/archives/1911</link>
		
		<dc:creator><![CDATA[Manuel Bogner]]></dc:creator>
		<pubDate>Wed, 08 Feb 2023 18:40:31 +0000</pubDate>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Kotlin]]></category>
		<guid isPermaLink="false">https://blog.coffeebeans.at/?p=1911</guid>

					<description><![CDATA[Using Spring Events can be very handy to decouple code. But have you ever tried creating generic events and then write a listener for them? Java or Kotlin themselves don&#8217;t prevent you from doing so but when you try receiving the events you will see that it doesn&#8217;t work. The reason for this is type [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Using Spring Events can be very handy to decouple code. But have you ever tried creating generic events and then write a listener for them? Java or Kotlin themselves don&#8217;t prevent you from doing so but when you try receiving the events you will see that it doesn&#8217;t work. The reason for this is type erasure. Generics are being removed during compilation. </p>



<p>Here a simple code sample for generic Crud events in a JPA application:</p>



<pre class="wp-block-code"><code>open class CrudEvent&lt;ID : Serializable, T : AbstractEntity&lt;ID&gt;&gt;

@EventListener
fun onEvent(event: CrudEvent&lt;UUID, User&gt;) {}</code></pre>



<p>Looks good, right? But doesn&#8217;t work. You could replace <code>CrudEvent&lt;UUID, User></code> with <code>CrudEvent&lt;*, *></code> and it would start receiving events. But of course all and not just for User. Here a simple way to get around this problem:</p>



<pre class="wp-block-code"><code>class UserEvent: CrudEvent&lt;UUID, User&gt;

@EventListener
fun onEvent(event: UserEvent) {}</code></pre>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>OAuth2 client with Spring Boot 3</title>
		<link>https://blog.mbo.dev/archives/1907</link>
		
		<dc:creator><![CDATA[Manuel Bogner]]></dc:creator>
		<pubDate>Tue, 31 Jan 2023 07:27:33 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Kotlin]]></category>
		<guid isPermaLink="false">https://blog.coffeebeans.at/?p=1907</guid>

					<description><![CDATA[With Spring Boot 3 some classes were deprecated and also the Keycloak adapter and the admin client stopped working in an application I am maintaining. In https://blog.coffeebeans.at/archives/1904 I already showed how to instantiate a WebClient which is the new way Spring wants us to call external APIs &#8211; not considering external libs like feign now. [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>With Spring Boot 3 some classes were deprecated and also the Keycloak adapter and the admin client stopped working in an application I am maintaining. In https://blog.coffeebeans.at/archives/1904 I already showed how to instantiate a WebClient which is the new way Spring wants us to call external APIs &#8211; not considering external libs like feign now. In Spring Security there is also an integration for OAuth2/OIDC compliant authentication. Taking the application mentioned above you need to have 2 dependencies in place:</p>



<pre class="wp-block-code"><code>    implementation("org.springframework.boot:spring-boot-starter-security")
    implementation("org.springframework.security:spring-security-oauth2-client")</code></pre>



<p>In your config you need to configure the OIDC server:</p>



<pre class="wp-block-code"><code>spring:
  security:
    oauth2:
      client:
        registration:
          keycloak:
            client-id: &lt;id>
            client-secret: &lt;secret>
            authorization-grant-type: client_credentials
        provider:
          keycloak:
            token-uri: &lt;server-url>/realms/&lt;realm>/protocol/openid-connect/token</code></pre>



<p>In the method you create your WebClient you need to add an oauth filter:</p>



<pre class="wp-block-code"><code>    @Bean
    @Qualifier("keycloak")
    @ConditionalOnMissingBean
    fun keycloakWebClient(
      clientRegistrations: ReactiveClientRegistrationRepository,
      authorizedClientService: ReactiveOAuth2AuthorizedClientService,
    ): WebClient {

        val oauth = ServerOAuth2AuthorizedClientExchangeFilterFunction(
                AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(
                        clientRegistrations, authorizedClientService
                )
        );
        oauth.setDefaultClientRegistrationId("keycloak");

        return WebClient.builder()
            .exchangeStrategies(ExchangeStrategies
                .builder()
                .codecs { clientDefaultCodecsConfigurer: ClientCodecConfigurer ->
                    clientDefaultCodecsConfigurer.defaultCodecs()
                        .jackson2JsonEncoder(Jackson2JsonEncoder(jsonMapper, MediaType.APPLICATION_JSON))
                    clientDefaultCodecsConfigurer.defaultCodecs()
                        .jackson2JsonDecoder(Jackson2JsonDecoder(jsonMapper, MediaType.APPLICATION_JSON))
                }.build()
            )
            .filter(WebClientLoggerBuilder.logRequest())
            .filter(oauth)
            .build()
    }</code></pre>



<p>This results in a WebClient instance using OAuth2 authentication with the server you configured for all calls you use it for. The mapping &#8220;keycloak&#8221; refers to the key &#8220;keycloak&#8221; in your application.yml&#8217;s <code>spring.security.oauth2.client.registration</code> and <code>spring.security.oauth2.client.provider</code>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Spring Boot WebClient with request logging</title>
		<link>https://blog.mbo.dev/archives/1904</link>
		
		<dc:creator><![CDATA[Manuel Bogner]]></dc:creator>
		<pubDate>Mon, 30 Jan 2023 17:36:17 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Kotlin]]></category>
		<guid isPermaLink="false">https://blog.coffeebeans.at/?p=1904</guid>

					<description><![CDATA[RestTemplate is dead and everybody should use WebClient now. That&#8217;s what you find everywhere so I had a look how to configure an instance of WebClient properly: This defines a bean genericWebClient with Spring Boot configured Jackson ObjectMapper instance. Here is also the code for the WebClientLoggerBuilder: This simply logs method, path and headers of [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>RestTemplate is dead and everybody should use WebClient now. That&#8217;s what you find everywhere so I had a look how to configure an instance of WebClient properly:</p>



<pre class="wp-block-code"><code>import com.fasterxml.jackson.databind.ObjectMapper
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.http.MediaType
import org.springframework.http.codec.ClientCodecConfigurer
import org.springframework.http.codec.json.Jackson2JsonDecoder
import org.springframework.http.codec.json.Jackson2JsonEncoder
import org.springframework.web.reactive.function.client.ExchangeStrategies
import org.springframework.web.reactive.function.client.WebClient

@Configuration
class WebClientConfig(
    private val jsonMapper: ObjectMapper,
) {

    @Bean
    @ConditionalOnMissingBean
    fun genericWebClient(): WebClient {
        return WebClient.builder()
            .exchangeStrategies(ExchangeStrategies
                .builder()
                .codecs { clientDefaultCodecsConfigurer: ClientCodecConfigurer -&gt;
                    clientDefaultCodecsConfigurer.defaultCodecs()
                        .jackson2JsonEncoder(Jackson2JsonEncoder(jsonMapper, MediaType.APPLICATION_JSON))
                    clientDefaultCodecsConfigurer.defaultCodecs()
                        .jackson2JsonDecoder(Jackson2JsonDecoder(jsonMapper, MediaType.APPLICATION_JSON))
                }.build()
            )
            .filter(WebClientLoggerBuilder.logRequest())
            .build()
    }
}</code></pre>



<p>This defines a bean genericWebClient with Spring Boot configured Jackson ObjectMapper instance.</p>



<p>Here is also the code for the WebClientLoggerBuilder:</p>



<pre class="wp-block-code"><code>import org.springframework.web.reactive.function.client.ClientRequest
import org.springframework.web.reactive.function.client.ExchangeFilterFunction
import reactor.core.publisher.Mono
import java.util.function.Consumer
import org.slf4j.Logger
import org.slf4j.LoggerFactory

object WebClientLoggerBuilder {

    private val log: Logger = LoggerFactory.getLogger(javaClass)

    fun logRequest(): ExchangeFilterFunction {
        return ExchangeFilterFunction.ofRequestProcessor { clientRequest: ClientRequest -&gt;
            if (log.isDebugEnabled) {
                val sb = StringBuilder("Request: \n")
                    .append(clientRequest.method())
                    .append(" ")
                    .append(clientRequest.url())
                    .append("\n")
                clientRequest.headers()
                    .forEach { name: String?, values: List&lt;String?&gt; -&gt;
                        values.forEach(
                            Consumer { value: String? -&gt; sb.append(name).append(": ").append(value).append("\n") })
                    }
                log.debug(sb.toString())
            }
            Mono.just(clientRequest)
        }
    }
}</code></pre>



<p>This simply logs method, path and headers of a request if debug log is enabled and added to the WebClient. Executing a blocking call that parses JSON to a list of objects is then quite easy:</p>



<pre class="wp-block-code"><code>fun &lt;T&gt; queryListWithoutBody(
    path: String,
    listClass: Class&lt;T&gt;,
    params: MultiValueMap&lt;String, String&gt;
): List&lt;T&gt; {
    return webClient.get()
        .uri { it.path(path).queryParams(params).build() }
        .retrieve()
        .bodyToFlux(listClass)
        .collectList()
        .block() ?: emptyList()
}</code></pre>



<p>With this code you&#8217;re able to replace RestTemplate without going reactive. Adding spring-boot-starter-webflux also won&#8217;t enable netty if you also have good old spring-boot-starter-web in the classpath.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>duplicate but no duplicate handling strategy has been set &#8211; gradle DuplicationStrategy</title>
		<link>https://blog.mbo.dev/archives/1874</link>
		
		<dc:creator><![CDATA[Manuel Bogner]]></dc:creator>
		<pubDate>Mon, 31 Oct 2022 23:15:20 +0000</pubDate>
				<category><![CDATA[gradle]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Kotlin]]></category>
		<guid isPermaLink="false">https://blog.coffeebeans.at/?p=1874</guid>

					<description><![CDATA[While using Java and Kotlin with Spring Boot the following exception occurs and it&#8217;s quite hard to find how to fix it. The simple solution is to add the following top level config in your gradle file:]]></description>
										<content:encoded><![CDATA[
<p>While using Java and Kotlin with Spring Boot the following exception occurs and it&#8217;s quite hard to find how to fix it.</p>



<pre class="wp-block-code"><code>1: Task failed with an exception.
-----------
* What went wrong:
Execution failed for task ':app:processResources'.
> Entry ... is a duplicate but no duplicate handling strategy has been set. Please refer to https://docs.gradle.org/7.5.1/dsl/org.gradle.api.tasks.Copy.html#org.gradle.api.tasks.Copy:duplicatesStrategy for details.
</code></pre>



<p>The simple solution is to add the following top level config in your gradle file:</p>



<pre class="wp-block-code"><code>tasks.withType&lt;Copy> {
    duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}</code></pre>



<p></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>java.lang.ClassNotFoundException: javax.annotation.PostConstruct</title>
		<link>https://blog.mbo.dev/archives/1860</link>
		
		<dc:creator><![CDATA[Manuel Bogner]]></dc:creator>
		<pubDate>Wed, 21 Sep 2022 09:38:55 +0000</pubDate>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JEE]]></category>
		<category><![CDATA[Kotlin]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">https://blog.coffeebeans.at/?p=1860</guid>

					<description><![CDATA[When upgrading to the latest tools and libraries in a Spring Boot application with OpenAPI code generator in place the OpenAPI Kotlin generator introduced jakarta.annotation:jakarta.annotation-api. But with this in place the application refused to start with something like org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat…Caused by: java.lang.IllegalStateException: [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>When upgrading to the latest tools and libraries in a Spring Boot application with OpenAPI code generator in place the OpenAPI Kotlin generator introduced <strong><em>jakarta.annotation:jakarta.annotation-api</em></strong>. But with this in place the application refused to start with something like</p>



<p><code><em>org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat<br>…<br>Caused by: java.lang.IllegalStateException: StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[] failed to start</em></code></p>



<p>Digging a bit deeper I found the real reason:</p>



<p><code><em>java.lang.NoClassDefFoundError: javax/annotation/PostConstruct</em></code></p>



<p>This can be fixed by also including <strong><em>javax.annotation:javax.annotation-api</em></strong> as a dependency. The new jakarta based library only includes <em>jakarta.annotation.*</em> but not <em>javax.annotation.*</em>. But Spring Boot still requires the old namespace to work. I didn&#8217;t dig deeper why including the dependency broke the app though it was working before without both of the dependencies.</p>



<p>Another great sample for how convenient this rename is and further will be.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>GitHub Detekt action with Detekt 1.19.0</title>
		<link>https://blog.mbo.dev/archives/1826</link>
		
		<dc:creator><![CDATA[Manuel Bogner]]></dc:creator>
		<pubDate>Tue, 15 Mar 2022 01:18:22 +0000</pubDate>
				<category><![CDATA[Kotlin]]></category>
		<guid isPermaLink="false">https://blog.coffeebeans.at/?p=1826</guid>

					<description><![CDATA[I created a github action config for detekt 1.19.0 based on Java 17 because the template from GitHub was using a much older version and also didn&#8217;t work for me.]]></description>
										<content:encoded><![CDATA[
<p>I created a github action config for detekt 1.19.0 based on Java 17 because the template from GitHub was using a much older version and also didn&#8217;t work for me.</p>



<pre class="wp-block-code"><code># This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
#
# This workflow performs a static analysis of your Kotlin source code using
# Detekt.
#
# Scans are triggered:
# 1. On every push to default and protected branches
# 2. On every Pull Request targeting the default branch
# 3. On a weekly schedule
# 4. Manually, on demand, via the "workflow_dispatch" event
name: Scan with Detekt

on:
  # Triggers the workflow on push or pull request events but only for default and protected branches
  push:
    branches: &#91; develop ]
  pull_request:
    branches: &#91; develop ]
  schedule:
     - cron: '31 13 * * 1'

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "scan"
  scan:
    name: Scan
    # The type of runner that the job will run on
    runs-on: ubuntu-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
    # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
    - uses: actions/checkout@v2
    - name: Set up JDK 17
      uses: actions/setup-java@v2
      with:
        java-version: '17'
        distribution: 'temurin'

    # Sets up the detekt cli
    - name: Setup detekt
      id: setup_detekt
      run: |
        dest=$( mktemp -d )
        DETEKT_FILE=$dest/detekt-cli-all.jar
        curl --request GET \
          --url https://github.com/detekt/detekt/releases/download/v1.19.0/detekt-cli-1.19.0-all.jar \
          --silent \
          --location \
          --output $DETEKT_FILE
        echo "::set-output name=detekt_file::$DETEKT_FILE"

    # Performs static analysis using Detekt
    - name: Run Detekt
      continue-on-error: true
      run: |
        java -jar ${{ steps.setup_detekt.outputs.detekt_file }} --input ${{ github.workspace }} --report sarif:${{ github.workspace }}/detekt.sarif.json

    # Modifies the SARIF output produced by Detekt so that absolute URIs are relative
    # This is so we can easily map results onto their source files
    # This can be removed once relative URI support lands in Detekt: https://git.io/JLBbA
    - name: Make artifact location URIs relative
      continue-on-error: true
      run: |
        echo "$(
          jq \
            --arg github_workspace ${{ github.workspace }} \
            '. | ( .runs&#91;].results&#91;].locations&#91;].physicalLocation.artifactLocation.uri |= if test($github_workspace) then .&#91;($github_workspace | length | . + 1):] else . end )' \
            ${{ github.workspace }}/detekt.sarif.json
        )" > ${{ github.workspace }}/detekt.sarif.json

    # Uploads results to GitHub repository using the upload-sarif action
    - uses: github/codeql-action/upload-sarif@v1
      with:
        # Path to SARIF file relative to the root of the repository
        sarif_file: ${{ github.workspace }}/detekt.sarif.json
        checkout_path: ${{ github.workspace }}
</code></pre>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>ArrayIndexOutOfBounds with Kotlin coroutines and Hibernate-Validator</title>
		<link>https://blog.mbo.dev/archives/1823</link>
		
		<dc:creator><![CDATA[Manuel Bogner]]></dc:creator>
		<pubDate>Mon, 14 Mar 2022 22:51:37 +0000</pubDate>
				<category><![CDATA[Kotlin]]></category>
		<guid isPermaLink="false">https://blog.coffeebeans.at/?p=1823</guid>

					<description><![CDATA[I was trying to build a spring boot application based on spring spring-boot-starter-webflux which is based on kotlinx-coroutines-reactor. The API definition was done with OpenAPI-Generator with &#8220;kotlin-spring&#8221; generator and &#8220;spring-boot&#8221; library. Setting the configOptions useBeanValidation and reactive to true generates suspendable methods and uses webflux. And adding hibernate-validator allows to use bean validation for every [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>I was trying to build a spring boot application based on spring <em>spring-boot-starter-webflux</em> which is based on <em>kotlinx-coroutines-reactor</em>. The API definition was done with OpenAPI-Generator with &#8220;kotlin-spring&#8221; generator and &#8220;spring-boot&#8221; library. Setting the configOptions <em>useBeanValidation</em> and <em>reactive</em> to true generates suspendable methods and uses webflux. And adding hibernate-validator allows to use bean validation for every request. Perfect. But trying the API for the first time ended in ArrayIndexOutOfBounds and it took me a while to find the reason until i found the following thread <a rel="noreferrer noopener" href="https://github.com/spring-projects/spring-framework/issues/23499" target="_blank">https://github.com/spring-projects/spring-framework/issues/23499</a>. In the conversation pschichtel posted a workaround that worked perfectly so far. You can find his classes under this link:</p>



<p><a href="https://gist.github.com/pschichtel/830b7943ea43b7cb58cadd984b54b903">https://gist.github.com/pschichtel/830b7943ea43b7cb58cadd984b54b903</a></p>



<p>Thx for the solution!</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Delegate value initialisation with &#8220;by lazy&#8221; in Kotlin</title>
		<link>https://blog.mbo.dev/archives/1819</link>
		
		<dc:creator><![CDATA[Manuel Bogner]]></dc:creator>
		<pubDate>Wed, 02 Mar 2022 21:45:53 +0000</pubDate>
				<category><![CDATA[Kotlin]]></category>
		<guid isPermaLink="false">https://blog.coffeebeans.at/?p=1819</guid>

					<description><![CDATA[Using unmodifiable variables &#8211; so called values in Kotlin with keyword val &#8211; should be the default where possible but it&#8217;s not always practical to initialise all values within the constructor. Kotlin offers the option to use &#8220;by lazy&#8221;. With some common kinds of properties, even though you can implement them manually every time you [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p> Using unmodifiable variables &#8211; so called values in Kotlin with keyword <code>val</code> &#8211; should be the default where possible but it&#8217;s not always practical to initialise all values within the constructor. Kotlin offers the option to use &#8220;by lazy&#8221;.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>With some common kinds of properties, even though you can implement them manually every time you need them, it is more helpful to implement them once, add them to a library, and reuse them later.</p><p> &#8211; Lazy properties: the value is computed only on first access.</p><p> &#8211; Observable properties: listeners are notified about changes to this property.</p><p> &#8211; Storing properties in a map instead of a separate field for each property.</p><cite><a href="https://kotlinlang.org/docs/delegated-properties.html">https://kotlinlang.org/docs/delegated-properties.html</a></cite></blockquote>



<p></p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p><a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/lazy.html"><code>lazy()</code></a> is a function that takes a lambda and returns an instance of <code>Lazy&lt;T></code>, which can serve as a delegate for implementing a lazy property. The first call to <code>get()</code> executes the lambda passed to <code>lazy()</code> and remembers the result. Subsequent calls to <code>get()</code> simply return the remembered result.</p><cite><a rel="noreferrer noopener" href="https://kotlinlang.org/docs/delegated-properties.html#lazy-properties" target="_blank">https://kotlinlang.org/docs/delegated-properties.html#lazy-properties</a> </cite></blockquote>



<p>The following test gives you an easy sample that allows you to use overridable member methods to calculate values on initialisation:</p>



<pre class="wp-block-code"><code>import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test

class ByLazyTest {

    @Test
    fun test() {
        val instanceA = A("a")
        val instanceB = B("b")

        assertThat(instanceA.testStr).isEqualTo("testStrGenA")
        assertThat(instanceA.value1).isEqualTo("a")
        assertThat(instanceB.testStr).isEqualTo("testStrGenB")
        assertThat(instanceB.value1).isEqualTo("b")
    }

    open class A constructor(
        val value1: String
    ) {
        val testStr: String by lazy { testStrGen() }

        open fun testStrGen(): String {
            return "testStrGenA"
        }
    }

    open class B constructor(
        value1: String
    ) : A(value1) {

        override fun testStrGen(): String {
            return "testStrGenB"
        }

    }
}</code></pre>



<p>This initialisation is by default synchronised.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
