Skip to content

Commit

Permalink
feat: allow Config injection (#1886)
Browse files Browse the repository at this point in the history
* feat: allow Config injection

* remove Config wiring to wiredInstance

* fixed workflow badwiring test
  • Loading branch information
octonato authored Nov 28, 2023
1 parent aaa0492 commit d9d0b78
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 30 deletions.
36 changes: 15 additions & 21 deletions maven-java/kalix-maven-plugin/src/main/scala/kalix/RunMojo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,29 +29,30 @@ object RunMojo {
log.warn("--------------------------------------------------------------------------------------")
}

if (jvmArgs.nonEmpty){
if (jvmArgs.nonEmpty) {
log.info("Additional JVM arguments detected: " + jvmArgs.toSeq.mkString(", "))
}

/*
* Collect any sys property starting with `kalix` and rebuild a -D property for each of them
* so we can pass it further to the forked process.
* Lookup for arguments passed to maven using -Dkey=value and rebuild a -D property for each of them.
*/
def collectKalixSysProperties: Seq[String] = {
sys.props.collect {
case (key, value) if key.startsWith("kalix") => s"-D$key=$value"
}.toSeq
}
def collectSysProperties: Seq[String] =
sys.env
.get("MAVEN_CMD_LINE_ARGS")
.map { args =>
args.split("\\s+").toSeq.collect {
case arg if arg.startsWith("-D") => arg
}
}
.getOrElse(Seq.empty)

val mainArgs =
Seq(
element(name("argument"), "-classpath"),
element(name("classpath")))



val kalixSysProps =
collectKalixSysProperties.map { arg =>
val sysProps =
collectSysProperties.map { arg =>
element(name("argument"), arg)
}

Expand All @@ -63,7 +64,7 @@ object RunMojo {
val additionalJvmArgs = jvmArgs.filter(_.trim.nonEmpty).map(element(name("argument"), _)).toSeq

val allArgs =
mainArgs ++ kalixSysProps ++ additionalJvmArgs ++ dockerConfig :+
mainArgs ++ sysProps ++ additionalJvmArgs ++ dockerConfig :+
element(name("argument"), mainClass) // mainClass must be last arg

executeMojo(
Expand Down Expand Up @@ -95,14 +96,7 @@ object RunMojo {
class RunMojo extends RunParameters {

override def execute(): Unit = {
RunMojo(
jvmArgs,
mainClass,
getLog,
mavenProject,
mavenSession,
pluginManager,
runningSolo = true)
RunMojo(jvmArgs, mainClass, getLog, mavenProject, mavenSession, pluginManager, runningSolo = true)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ object KalixRunner {
DevModeSettings.addDevModeConfig(mainConfig)
}

private def loadConfig(): Config = prepareConfig(ConfigFactory.load())
private def loadPreparedConfig(): Config = prepareConfig(ConfigFactory.load())

}

Expand All @@ -116,8 +116,10 @@ final class KalixRunner private[javasdk] (

private val dockerComposeUtils = DockerComposeUtils.fromConfig(_system.settings.config)

// The effective Akka Config instance as it maybe be tweaked for dev-mode (see KalixRunner.prepareConfig)
private[kalix] val finalConfig: Config = system.settings.config
private[kalix] final val configuration =
new KalixRunner.Configuration(system.settings.config.getConfig("kalix"))
new KalixRunner.Configuration(finalConfig.getConfig("kalix"))

private val services = serviceFactories.toSeq.map { case (serviceName, factory) =>
serviceName -> factory(system)
Expand All @@ -127,14 +129,18 @@ final class KalixRunner private[javasdk] (
* Creates a KalixRunner from the given services. Use the default config to create the internal ActorSystem.
*/
def this(services: java.util.Map[String, java.util.function.Function[ActorSystem, Service]], sdkName: String) = {
this(ActorSystem("kalix", KalixRunner.loadConfig()), services.asScala.toMap, aclDescriptor = None, sdkName)
this(ActorSystem("kalix", KalixRunner.loadPreparedConfig()), services.asScala.toMap, aclDescriptor = None, sdkName)
}

def this(
services: java.util.Map[String, java.util.function.Function[ActorSystem, Service]],
aclDescriptor: Option[FileDescriptorProto],
sdkName: String) =
this(ActorSystem("kalix", KalixRunner.loadConfig()), services.asScala.toMap, aclDescriptor = aclDescriptor, sdkName)
this(
ActorSystem("kalix", KalixRunner.loadPreparedConfig()),
services.asScala.toMap,
aclDescriptor = aclDescriptor,
sdkName)

/**
* Creates a KalixRunner from the given services and config. The config should have the same structure as the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ case class KalixSpringApplication(applicationContext: ApplicationContext, config
// last case is a catch all that lookups in the applicationContext
val totalWireFunction: PartialFunction[Class[_], Any] =
partial.orElse {
case p if p == classOf[Config] => kalixRunner.finalConfig
// block wiring of clients into anything that is not an Action or Workflow
// NOTE: if they are allowed, 'partial' should already have a matching case for them
case p if p == classOf[KalixClient] =>
Expand Down Expand Up @@ -424,26 +425,37 @@ case class KalixSpringApplication(applicationContext: ApplicationContext, config
ReflectiveEventSourcedEntityProvider.of(
clz,
messageCodec,
context => wiredInstance(clz) { case p if p == classOf[EventSourcedEntityContext] => context })
context =>
wiredInstance(clz) {
case p if p == classOf[EventSourcedEntityContext] => context
})

private def valueEntityProvider[S, VE <: ValueEntity[S]](clz: Class[VE]): ValueEntityProvider[S, VE] =
ReflectiveValueEntityProvider.of(
clz,
messageCodec,
context => wiredInstance(clz) { case p if p == classOf[ValueEntityContext] => context })
context =>
wiredInstance(clz) {
case p if p == classOf[ValueEntityContext] => context
})

private def viewProvider[S, V <: View[S]](clz: Class[V]): ViewProvider =
ReflectiveViewProvider.of[S, V](
clz,
messageCodec,
context => wiredInstance(clz) { case p if p == classOf[ViewCreationContext] => context })
context =>
wiredInstance(clz) {
case p if p == classOf[ViewCreationContext] => context
})

private def multiTableViewProvider[V](clz: Class[V]): ViewProvider =
ReflectiveMultiTableViewProvider.of[V](
clz,
messageCodec,
(viewTableClass, context) => {
val constructor = viewTableClass.getConstructors.head.asInstanceOf[Constructor[View[_]]]
wiredInstance(constructor) { case p if p == classOf[ViewCreationContext] => context }
wiredInstance(constructor) {
case p if p == classOf[ViewCreationContext] => context
}
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,13 @@

package kalix.spring.badwiring.workflow;

import kalix.javasdk.annotations.Id;
import kalix.javasdk.annotations.TypeId;
import kalix.javasdk.workflow.Workflow;
import org.springframework.stereotype.Component;

@Id("id")
@TypeId("test")
@Component
public class IllDefinedWorkflow extends Workflow<String> {
@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ public class Main {

public static void main(String[] args) {
logger.info("Starting Kalix Application");
SpringApplication.run(kalix.spring.badwiring.view.Main.class, args);
SpringApplication.run(Main.class, args);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import kalix.spring.badwiring.valueentity
import kalix.spring.badwiring.valueentity.IllDefinedValueEntity
import kalix.spring.badwiring.view
import kalix.spring.badwiring.view.IllDefinedView
import kalix.spring.badwiring.workflow
import kalix.spring.badwiring.workflow.IllDefinedWorkflow
import kalix.spring.boot.KalixConfiguration
import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec
Expand Down Expand Up @@ -82,6 +84,15 @@ class KalixSpringApplicationSpec extends AnyWordSpec with Matchers {

errorMessage shouldBe KalixConfiguration.beanPostProcessorErrorMessage(classOf[IllDefinedView])
}

"block direct wiring of Kalix Workflows" in {
val errorMessage =
intercept[BeanCreationException] {
tryCatch(() => workflow.Main.main(Array.empty))
}.getCause.getMessage

errorMessage shouldBe KalixConfiguration.beanPostProcessorErrorMessage(classOf[IllDefinedWorkflow])
}
}

}

0 comments on commit d9d0b78

Please sign in to comment.