-
Notifications
You must be signed in to change notification settings - Fork 343
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Generate both interface and type from abstract class #220
Comments
Hello @StarF666, Do you have a snippet of code showing showing the Kotlin sources and the expected GraphQL schema output? Thanks |
Here is a sample model with the same structure like I'm using for my persistence layer (without the JPA annotations obviously): abstract class Vehicle(
open val name: String
)
class Car(
override val name: String,
val doors: Int
) : Vehicle(name)
class Bicycle(
override val name: String,
val gears: Int
) : Vehicle(name)
And this is what would be needed as a GraphQL schema: interface VehicleInterface {
name: String!
}
type Vehicle implements VehicleInterface {
name: String!
}
type Car implements VehicleInterface {
doors: Int!
name: String!
}
type Bicycle implements VehicleInterface {
gears: Int!
name: String!
}
type Query {
getVehicle(type: String!): [VehicleInterface!]!
}
Currently it only creates the "type vehicle" but no interface so I can query for a vehicle but cannot use a query like this: query {
getVehicle(type: "any") {
name,
...on Bicycle {gears}
...on Car {doors}
}
}
I hope this clarifies it a bit. I know it seems a bit odd to generate an interface although there isn't one on the kotlin side but GraphQL does not support direct type inheritance (as far as I know). Thanks for taking your time. |
Fix released in 0.3.1 |
Thanks for your work. I tested the new version against my model and found another issue. Here is an updated test model which causes the following error:
Test model: abstract class BaseTestEntity(
val id: Int = -1
)
class Feature(val name: String) : BaseTestEntity()
abstract class Vehicle(
open var name: String = "Mustang",
open var features: List<Feature> = listOf()
) : BaseTestEntity()
class Bicycle(
override var name: String,
var gears: Int,
override var features: List<Feature>
) : Vehicle(name, features)
class Car(
override var name: String,
var doors: Int,
override var features: List<Feature>
) : Vehicle()
I added a class "Feature" which each Vehicle has a list of and whcih also inherits from BaseTestEntity. This inheritance causes the trouble. I'm not really sure, what the generated schema should look like or if I'm hitting some boundary here. P.S.: I get the same error when I change the abstract classes to interfaces. |
GraphQL cant have an interface implement another interface today, so this is is not an error but "expected" graphql/graphql-spec#373 I agree that it is limiting now in Kotlin code but if you think in terms of the resulting schema and how you would query this it makes it very complicated. query MultiInterface {
getAllEntities {
id
... on Vehicle {
name
# double nested fragment!
... on Car {
doors
}
}
}
} |
Thanks again for your effort. I will watch GraphQL spec and see if/how they will extend their inhereritance system. I understand the problem with circular references from your previous comment. Currently my problem is with said base classes abstracting technical database concerns. So to make my model finally work, I used custom hook "isValidSuperclass" to exclude my base classes from schema generation: override fun isValidSuperclass(kClass: KClass<*>): Boolean {
return when (kClass.qualifiedName) {
"com.acme.somepackage.BaseEntity" -> false
"com.acme.somepackage.AuditedEntity" -> false
else -> true
}
}
|
I'm currently still playing around with graphql-kotlin. Biggest "issue" currently for me is that I'm using abstract classes in my model to implement base classes for some entity types (using hibernate to access database). When using the generator this generates a schema where I cannot query for a base type and then use the "...on SomeType" syntax to handle the subclasses. I would have to write interfaces mirroring the abstract classes properties which would mean repeating my code.
I thought about changing the generator so it will generate a type AND interface from an abstract kotlin class. But I was not able to dig deep enough into the generators code to archieve this. It is easy to generate an interface instead of a type but not two (interface and type).
I don't know if this would break any rules or conventions of GraphQL. I really like what I discovered so far but GraphQL seems to be a bit limited with inheritance. I could manually write the interfaces but that would mean double source of truth.
Maybe I'm missing something but would the solution of generating both interface and type be a feasible solution?
The text was updated successfully, but these errors were encountered: