google / google/guice

What could be the reason for Kotlin Result class not playing well with constructor injection?

Open
#1,641 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
12.7k
Forks
1.7k
Avg merge
11m
Merged PRs (30d)
2

Description

This is just an example but hopefully illustrates the problem. All seem to be related to the Kotlin Result class. For other generic classes like e.g. java Optional or self-made Kotlin generic class, all work as expected and both implementations in the given example are injected properly.

Binding configuration looks like this:

```
import com.google.inject.AbstractModule
import com.google.inject.Singleton
import com.google.inject.TypeLiteral

class BillingModule : AbstractModule() {

override fun configure() {
bind(object :
TypeLiteral>>() {}).toProvider(CreditCardProcessorProvider::class.java)
.`in`(Singleton::class.java)

bind(object : TypeLiteral>>() {}).toProvider(DebitCardProcessorProvider::class.java)
.`in`(Singleton::class.java)
}

}
```

Guice card providers:

```
import com.google.inject.Provider

class CreditCardProcessorProvider : Provider>> {

private val creditCardProcessor = CreditCardProcessor>()

override fun get(): CardProcessor> {
return creditCardProcessor
}

}

```
```
import com.google.inject.Provider

class DebitCardProcessorProvider : Provider>> {

private val debitCardProcessor = DebitCardProcessor>()

override fun get(): CardProcessor> {
return debitCardProcessor
}

}
```

and the service with constructor injection:

```
import javax.inject.Inject

class RealBillingService @Inject constructor(
private val creditCardProcessor: CardProcessor>,
private val debitCardProcessor: CardProcessor>,
) {

fun chargeOrder() {
val creditCardOutput = creditCardProcessor.charge(Result.success("ok"))
val debitCardOutput = debitCardProcessor.charge(Result.success(1))
}

}
```

Unfortunately, this configuration results in the following exception:
```
1) [Guice/MissingImplementation]: No implementation for CardProcessor> was bound.

Requested by:
1 : RealBillingService.(RealBillingService.kt:3)
\_ for 2nd parameter
while locating RealBillingService

Learn more:
https://github.com/google/guice/wiki/MISSING_IMPLEMENTATION

2) [Guice/MissingImplementation]: No implementation for CardProcessor> was bound.

Requested by:
1 : RealBillingService.(RealBillingService.kt:3)
\_ for 1st parameter
while locating RealBillingService
```

What is also interesting is that the given configuration, when accessing a concrete implementation of a card processor manually, returns the expected value correctly. Wondering how this could be fixed on constructor injection? From my side already tried with [named bindings][1] and [binding annotations][2] but without luck.

```
var creditCardProcessor =
injector.getInstance(Key.get(object : TypeLiteral>>() {}))
```

[1]: https://www.tutorialspoint.com/guice/guice_named_binding.htm
[2]: https://www.tutorialspoint.com/guice/guice_binding_annotations.htm

Kotlin version: 1.7.10

Guice version: com.google.inject:guice:5.1.0

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.