Marcin Small-ski
Marcin Small-ski

Reputation: 171

CDI inject specific interface implementation

Say I have an interface Config and two clasess implementing this interface:

class Config1: Config {
}

class Config2: Config {
}

I create one of those implementations by deserializing JSON using Jackson and want to provide it as CDI ApplicationScope bean in the common library:

@Produces
@ApplicationScope
fun config: Config {
  return mapper.readValue(json, Config)
}

Now I have two applications, App1 rely on Config1 and App2 on Config2. I'd like to achieve the bahaviour that for example starting App1 Config1 is injected or Exception is thrown that there's no bean to satisfy constructor. Unfortunatelly this doesn't work:

class App1 (val config: Config1) { }

Is there any way to achieve it? Or i have to write a service that would do the instance check?

Upvotes: 1

Views: 559

Answers (1)

Siliarus
Siliarus

Reputation: 6753

You might need to re-think the approach. With what you have, you cannot even perform instanceof check because you will be getting a proxy, not the actual bean instance (since your producer is @ApplicationScoped).

In CDI, beans are defined by their types and their qualifiers. From your description I understand that you need to differentiate between the two config anyway, so abstracting it into just interface won't work. You could have two producer methods, each for one of the configs and with different qualifiers. Each method looking something like this:

@Produces
@ApplicationScoped
@Config1Qualifier //some custom qualifier that you slap on it
fun config: Config {
  return someFunctionThatResolvesIt()
}

The injection point for it would then look like this (using Java syntax):

@Inject
@Config1Qualifier
Config config;

The upside of this approach is that so long as your producer methods have normal scopes on them (such as @ApplicationScoped), then if they attempt to return null, it is automatically treated as an error - which looks like something you are trying to achieve anyway.

Approaching it from a completely different angle, you could take your current producer method and change @ApplicationScoped to @Dependent or @Singleton none of which use proxies and would allow to perform instanceof. But mind that specifically @Dependent might behave differently from what you want (just assuming you are using app scoped to keep singular instance).

Upvotes: 1

Related Questions