kalix-jvm-sdk icon indicating copy to clipboard operation
kalix-jvm-sdk copied to clipboard

Inject KalixClient or WebClientProvider to Spring components.

Open aludwiko opened this issue 1 year ago • 9 comments

Currently, I don't allow it KalixClient can only be injected in Kalix Actions and Workflows., but is there a technical reason behind it? I understand that injecting Kalix entities would cause a lot of confusion, but clients?

My rationale behind it: I have a subscription that launches some actions against a Kalix component via KalixClient. I would like to simulate a disturbance in my system, e.g. a timeout or sth that will slow down, or even restart the whole projection/subscription. My idea was to wrap the KalixClient with Spring bean and inject this bean into the subscription action. In a test, I would override this bean definition with a failing one, via @MockBean or any other mechanism.

Maybe I'm solving the wrong problem, any thoughts?

aludwiko avatar May 29 '23 12:05 aludwiko

We don't want it injected in entities (async callbacks over state that may have changed since etc) could perhaps be one reason. But maybe it would be possible to block just those instead (and components transitively injected into entities, maybe that is the tricky part)?

johanandren avatar May 29 '23 16:05 johanandren

It's already not possible to inject Kalix components into other Kalix components, but also not possible to inject Kalix components in any other place. Basically, Kalix components always be at the top level.

Injecting a client in a non Kalix components is in principle not a problem, but could leave to the following situations:

(java pseudo-code ahead)

class SomeOtherComponent(WebClientProvider webClientProvider)

class MyKalixEntity(SomeOtherComponent someOtherComponent) extends EventSourcedEntity {
  
  private WebClient client = someOtherComponent.webClientProvider.clientFor(...)
}

Now we can have a client inside an entity.

octonato avatar May 29 '23 21:05 octonato

Well, if you want to hack the entity, you can do this anyway with a static method.

aludwiko avatar May 30 '23 07:05 aludwiko

Transitively calling some other service through an injected component is not something I'd call a hack, rather something that we should guard against if we want Kalix to guide users to not do bad design. Or we decide that we don't care and it is their problem, if that is the direction we want to go I think we can allow injecting the client directly in entities as well but there will be concurrency issues lurking there for users if they mix entity logic with async callbacks.

johanandren avatar May 30 '23 07:05 johanandren

I think we have to do this anyway because most of the effect builders allow us to run a forward call:

effects()
        .updateState(???)
        .thenForward(???)

aludwiko avatar Jun 16 '23 10:06 aludwiko

Related issue for forward: https://github.com/lightbend/kalix-jvm-sdk/issues/673

johanandren avatar Jun 16 '23 10:06 johanandren

I don't recall that I have pledged for this (#673), but that's consistent with what I usually think.

octonato avatar Jun 20 '23 11:06 octonato

Ok, what about the side effects?

  static SideEffect of(DeferredCall serviceCall, boolean synchronous) {
    return new SideEffectImpl(serviceCall, synchronous);
  }

  static SideEffect of(DeferredCall serviceCall) {
    return new SideEffectImpl(serviceCall, false);
  }

aludwiko avatar Jun 26 '23 10:06 aludwiko

I think we will have to keep supporting it.

In #673, Johan also mentions side effects. I agree that forward and side effects don't seem very useful inside entities, but at least we do not support async calls.

octonato avatar Jun 27 '23 11:06 octonato