Skip to content

Commit

Permalink
Add support for GraalVM native-image (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
cmdjulian authored Apr 23, 2024
1 parent 2d7c9b8 commit cc3c304
Show file tree
Hide file tree
Showing 10 changed files with 36 additions and 8 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,10 @@ class TestService(private val mqttClient: Mqtt3Client) {
}
```

### GraalVM

This starter supports GraalVM out of the box. There is nothing special to do.

### Upgrade Guide

#### 0.15.0 -> 0.16.0
Expand Down
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ kotlin {
compilerOptions {
jvmTarget = JvmTarget.JVM_17
allWarningsAsErrors = true
javaParameters = true
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import com.hivemq.client.mqtt.mqtt5.Mqtt5Client
import io.reactivex.Scheduler
import io.reactivex.schedulers.Schedulers
import org.slf4j.LoggerFactory
import org.springframework.aot.hint.annotation.RegisterReflectionForBinding
import org.springframework.boot.autoconfigure.AutoConfiguration
import org.springframework.boot.autoconfigure.AutoConfigureAfter
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass
Expand All @@ -30,6 +31,7 @@ import java.util.concurrent.Executor
@Import(MqttSubscriberCollector::class)
@ConditionalOnClass(MqttClient::class)
@ConditionalOnProperty("mqtt.enabled", matchIfMissing = true)
@RegisterReflectionForBinding(MqttProperties::class)
@EnableConfigurationProperties(MqttProperties::class)
class MqttAutoConfiguration {

Expand Down Expand Up @@ -126,6 +128,7 @@ class MqttAutoConfiguration {
fun immediateMqttScheduler(): Scheduler = Schedulers.computation()

@Bean
@ConditionalOnMissingBean
fun mqttMessageAdapter(objectMapper: ObjectMapper): MqttMessageAdapter = DefaultMqttMessageAdapter(objectMapper)

/**
Expand Down
4 changes: 2 additions & 2 deletions src/main/kotlin/de/smartsquare/starter/mqtt/MqttProperties.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ data class MqttProperties(
/**
* The port the mqtt broker is available under.
*/
@field:Min(1)
@field:Max(65535)
@get:Min(1)
@get:Max(65535)
val port: Int = 0,

/**
Expand Down
2 changes: 2 additions & 0 deletions src/main/kotlin/de/smartsquare/starter/mqtt/MqttSubscribe.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package de.smartsquare.starter.mqtt

import com.hivemq.client.mqtt.datatypes.MqttQos
import org.springframework.aot.hint.annotation.Reflective

/**
* Marker annotation for methods that should receive messages from the mqtt broker.
*/
@Reflective
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
annotation class MqttSubscribe(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,26 @@ package de.smartsquare.starter.mqtt
import com.hivemq.client.mqtt.datatypes.MqttQos
import com.hivemq.client.mqtt.datatypes.MqttTopicFilter
import org.slf4j.LoggerFactory
import org.springframework.beans.factory.ObjectProvider
import org.springframework.beans.factory.config.BeanPostProcessor
import org.springframework.context.annotation.Lazy
import org.springframework.core.annotation.AnnotationUtils
import java.lang.reflect.Method

/**
* Helper class to find all beans with methods annotated with [MqttSubscribe].
*/
class MqttSubscriberCollector(@Lazy private val config: MqttProperties) : BeanPostProcessor {
class MqttSubscriberCollector(configProvider: ObjectProvider<MqttProperties>) : BeanPostProcessor {

private val logger = LoggerFactory.getLogger(javaClass)

/**
* It's really important to use lazy initialization here, because the bean value inside this provider is not
* available during construction time and only requested lazy up on the first found subscriber.
* At this point, the bean is already available and can be used.
* We cache the result here to avoid multiple expensive lookups from the underlying bean factory.
*/
private val config: MqttProperties by lazy { configProvider.`object` }

/**
* MultiMap of beans to its methods annotated with [MqttSubscribe] and the annotation itself.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import org.junit.jupiter.api.Nested
import org.junit.jupiter.api.Test

object TestMqttSubscriberCollector {
operator fun invoke(bean: Any): MqttSubscriberCollector = MqttSubscriberCollector(MqttProperties()).apply {
operator fun invoke(bean: Any) = MqttSubscriberCollector(TestObjectProvider(MqttProperties())).apply {
postProcessAfterInitialization(bean, "testBean")
}
}
Expand All @@ -21,7 +21,7 @@ class MqttHandlerTest {
private val messageErrorHandler = MqttMessageErrorHandler()

@Test
fun `invoke correct method for multiple subsciber methods`() {
fun `invoke correct method for multiple subscriber methods`() {
val subscriber = object {
var invoked = false

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class MqttSubscriberCollectorIntegrationTests {
class PostProcessorConfiguration {

@Bean
fun annotationCollector() = MqttSubscriberCollector(MqttProperties())
fun annotationCollector() = MqttSubscriberCollector(TestObjectProvider(MqttProperties()))

@Bean
fun subscriber() = Subscriber()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import org.junit.jupiter.api.Test

class MqttSubscriberCollectorTests {

private val annotationCollector = MqttSubscriberCollector(MqttProperties(group = "group"))
private val annotationCollector = MqttSubscriberCollector(TestObjectProvider(MqttProperties(group = "group")))

@Test
fun `processes bean`() {
Expand Down
10 changes: 10 additions & 0 deletions src/test/kotlin/de/smartsquare/starter/mqtt/TestObjectProvider.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package de.smartsquare.starter.mqtt

import org.springframework.beans.factory.ObjectProvider

class TestObjectProvider<T : Any>(private val data: T) : ObjectProvider<T> {
override fun getObject(vararg args: Any?): T = data
override fun getObject(): T = data
override fun getIfAvailable(): T = data
override fun getIfUnique(): T = getObject()
}

0 comments on commit cc3c304

Please sign in to comment.