Comments (11)
EDIT: I got things mixed up. The issue here is with Jackson, not SPQR. See my comment below.
In a way, this is expected... Because SPQR expects the JavaBean naming convention. At least in Java, there is no relationship between the field and the setter beyond the naming convention and a matching type. So if the naming scheme is violated, there's no clear way of knowing the relationship exists. In Kotlin, the relationship is likely maintained by different means (and I expect Kotlin reflection to be aware of it), but SPQR isn't really aware of Kotlin, so the issue described above occurs.
What I had always been advocating for is a Kotlin aware module, (that would ideally be written in Kotlin, although Java works fine too) that takes care of all Kotlin specific behaviors. It would likely be a small module, without much complications. But. It would ideally be community maintained, as I'm not all that familiar with Kotlin. If you'd care to contribute such a thing, just with this one fix, I'd happily take it as a start.
from graphql-spqr.
Would such a module for SPQR solve this specific case?
or is this a problem with graphql-java?
from graphql-spqr.
Ignore (almost) everything I said. I got confused 🤦♂️
This is about Jackson, nothing else. You just have to add jackson-module-kotlin. That makes Jackson understand Kotlin properties correctly. The root issue is the naming convention, as I described above, but in Jackson, not in SPQR.
from graphql-spqr.
jackson-module-kotlin has already been added to my project.
How do i apply it to graphql-spqr?
from graphql-spqr.
Huh. SPQR normally calls objectMapper.findAndRegisterModules()
so it should find it automatically.
But I don't know how or what is customized etc. Try:
generator.withValueMapperFactory(JacksonValueMapperFactory.builder()
.withPrototype(new ObjectMapper()) //customize ObjectMapper as you please, e.g. add a module
.build())
If you're using SPQR with Spring, you might want to use the Spring-provided ObjectMapper
instance (I don't actually advise this, but it might be a good test).
from graphql-spqr.
If that doesn't help... then Jackson is weird about Kotlin?
The thing to note here is that SPQR delegates (almost) all input deserialization to Jackson. So Jackson decides how to instantiate the object and populate its fields. No clue why it would decide against using the setter though 🤷♂️ Can you try messing with your class and Jackson directly, and see how it behaves?
from graphql-spqr.
I tired this quickly* and I indeed do not get "Hello world" printed:
class MyTest {
var isAlive: Boolean? = null
set(value) {
field = value
println("Hello world")
}
}
fun main(args:Array<String>) {
val clazz: Class<MyTest> = MyTest::class.java
ObjectMapper().registerModules(KotlinModule.Builder()
.enable(KotlinFeature.KotlinPropertyNameAsImplicitName).build())
.readValue("{ \"isAlive\": true }", clazz)
}
So either I did something wrong (did I?) or Jackson did...
*not actually quickly 😶
from graphql-spqr.
Actually... the more I look at this the more sense it makes.
Jackson isn't doing anything wrong. Without KotlinPropertyNameAsImplicitName
, it sees isAlive
and decides the property is called alive
, as per JavaBeans convention. With KotlinPropertyNameAsImplicitName
the property is called isAlive
but such a property doesn't have a setter. Jackson is simply following the spec, just like SPQR. So you'd have to do some further customizations if to achieve what you want. I can help you do that, but... I first have to ask: why go against the JavaBeans spec in the first place? It exists for a reason and tools and libraries are expecting it to be respected. Why go against the grain here?
from graphql-spqr.
The easiest you can do is:
class MyTest {
var isAlive: Boolean? = null
@JsonSetter("isAlive")
set(value) {
field = value
println("Hello world")
}
}
fun main(args:Array<String>) {
val clazz: Class<MyTest> = MyTest::class.java
ObjectMapper() //No KotlinPropertyNameAsImplicitName
.readValue("{ \"isAlive\": true }", clazz)
}
It prints "Hello world" as expected. You could probably achieve the same with @GraphQLInputField(name = "isAlive")
.
There are also a couple of ways to ensure this is applied everywhere. I can whip something up if you're sure that's what you need.
from graphql-spqr.
I actually tried this myself some time ago and reached the same conclusion.
You will get a "Hello world" if you rename it to 'alive' by dropping the isX prefix.
Which seems to confirm that the bug is indeed in jackson.
Thank you for your assistance.
I will bring the issue to them.
from graphql-spqr.
Actually didn't see your last 2 messages.
So i think the JavaBean convention probably makes sense for Java.
But it doesn't seem to play well with Kotlin here.
It makes more sense for me to write a property in Kotlin named 'isAlive' rather than 'alive'.
Kotlin doesn't need to specify explicit getter and setter methods as that is handled by Kotlin compiler.
I normally don't think about or care about how this is translated into java's getters and setters.
If anything maybe it is the Kotlin language designers who should have tried to make Kotlin compatible with JavaBeans convention.
Your @JsonSetter solution is interesting, i may use that as a fallback.
But before that i will try to contact jackson maintainers to see what they have to say.
from graphql-spqr.
Related Issues (20)
- How to use executionResult data HOT 2
- Failing tests - ComplexityTest class
- Explicitly register Java classes to the GraphQL schema. HOT 4
- How to map a java class to GraphQL interface without using @GraphQLInterface annotation? HOT 5
- Best way to error handling HOT 1
- Help in Handling Exceptions with SPQR HOT 1
- Question: Extending an InputObject type and handle it in SPQR HOT 3
- SDL Printing Fails on Schema Directives with Arguments HOT 4
- Spring 3.2: Cannot resolve parameter names for constructor public io.leangen.graphql.spqr.spring.web.dto.GraphQLRequest(java.lang.String,java.lang.String,java.lang.String,java.util.Map) HOT 2
- Compile parameters to support Spring Boot 3.2.1 (Spring Framework 6.1) HOT 1
- null values sent in response json HOT 1
- Schema Generation Regression in 0.12.4 HOT 1
- Polymorphism type on input
- Scalars containing an Instant cannot be serialized over subscription
- Schema generation at compile time?
- BUG: The DelegatingTypeResolver breaks when updating the GraphQLSchema using a Visitor HOT 1
- Feature Request: Add support for GraphQLOutputType to the SchemaTransformer HOT 39
- Make a public OperationMapper#createResolver overload to help with creating custom field resolvers
- Mark the gson-java8-datatype dependency as optional HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from graphql-spqr.