-
Notifications
You must be signed in to change notification settings - Fork 312
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
Allow custom scalar, parsed to different types, to bind onto java.lang.Object
#447
Comments
Did you try implementing the For reference, see |
Hi @djselzlein, Thanks for you answer, I tried with the I don't think there is a problem with our custom scalar type, it works perfectly with the kickstart library. I created a branch on the repo, with the same query but using the kickstart library and there is no error (you have to start the project to test). |
Thanks for the sample. The case seems to be a custom scalar type parsed into a Our GraphQL argument binding mechanism takes into account both the GraphQL arguments map and the type information from the target object. Typically, target types are more specific, e.g. complex objects to be created from generic maps, lists, and scalars. So the binding relies on type information from the target to decide what to instantiate, what to convert, etc. In this case, however, the target is We could make an exception specifically where the target is Alternatively, you could make this a bit more explicit by creating a Java type with both a class CustomValue {
private String stringValue;
private List<String> stringValue;
// ...
} Yet another alternative is to just read the raw arguments map, which in this case is quite simple. As to why this worked in Kickstart, I can't say for sure, but I suspect its binding mechanism might involve serializing the GraphQL arguments map to JSON and then back to the target Object. That would probably work in your case, but more generally we ran into problems with that approach, see #122. |
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed. |
I just put this 2 options (String or list of String) in the repo to reproduce the problem but we can have anything in this field (an integer, a list of integer, some complex object...). We would not like explicit all possibilities (like your proposal of I would like to point out that it fails only if the list is in an input object, it works if the list is directly passed as input. The query We can see in the stacktrace that the error is not at graphql-java lib level. The main branch of the repo to reproduce contains an example with the |
Did you read the rest of my comment? I provided an explanation and proposed a solution. What do you think about it? |
Yes we read your comment entirely (at least 10 times). I'm sorry, english is not our native language, I'm afraid we missed something. I guess I understand your explanation and I thought I answered to your proposal of
I'm not sure if this is a proposal of solution, if so I think it can be great to implement this, it corresponds exactly to :
I guess this is an alternative of implementation for you ? I don't see where I can read the raw arguments map myself. |
Okay, no worries. Just wanted to make sure we understand each other before I proceed with any changes.
Yes, that's my proposal, and I'll go ahead with it.
You can always declare |
java.lang.Object
java.lang.Object
java.lang.Object
I spoke too soon. In the present implementation, which relies on That said, I did make a change so you can do this via constructor binding. Adjusting your example to the below should work: public class BusinessEntityFilterInput {
private final String operator;
private final Object value;
public BusinessEntityFilterInput(String operator, Object value) {
this.operator = operator;
this.value = value;
}
public String getOperator() {
return operator;
}
public Object getValue() {
return value;
}
} As I mentioned in my last comment, you can also bypass data binding completely, and work with the raw arguments map: @QueryMapping
public boolean filterValueIsInstanceOfList(@Argument Map<String, Object> filter) {
return filter.get("value") instanceof List;
} |
Hi @rstoyanchev, Thanks for your work. I would like test this 1.0.2 release but I can't find them in the central repo (https://mvnrepository.com/artifact/org.springframework.graphql/spring-graphql). Even if I found it in the search maven site (https://search.maven.org/artifact/org.springframework.graphql/spring-graphql/1.0.2/jar). I waited but it was 2 days ago, do you know why this release is not available ? |
I'm not sure why it's not showing up in the UI, but it is there in the repo and has been for 2 days. It should work fine in your Maven or Gradle build. |
My bad it's just an UI problem. I tried with the release 1.0.2 and I still have the error. I debug and I figure out that exception is throw before your modification (else if added at line 287 of GraphQLArgumentBinder class). Problems occurs when |
Could you clarify if you switched to using constructor args or not? As I explained in #447 (comment), there is no simple way to fix the issue when using setters for your Object property, but it should work if you switch to constructor args. |
My bad again, when I first read your comment i said to myself "don't forget to do this", but I did... All is ok when I made what you said. Thanks you |
Note that in 1.1.x, this issue should be fixed also for the case with setters/getters, see #516. |
Hi,
We are migrating an application to Spring Graphql library from kickstart library, we have working queries/mutations. Our application has several queries to get a list of business entity with an input containing a generic filter object (field, operator and value). This filter input has a
value
property which is anObject
type : depending on the operator (equal
orin
) it could be aString
or aList
(or anything else). We have created aGraphQLScalarType
Object to represent this field.We have an issue with this filter input and the scalar type for array values. When we pass an array of values we have this exception (the same works with the kickstart library):
There is no issue if the scalar type is used directly as input type.
We pushed a minimal application with tests to reproduce the error :
BusinessEntityControllerTests
class (it is possible to start the application and send queries)The application contains 2 queries :
filterValueIsInstanceOfList
which return true if the value of input filter object is instance ofList
inputIsInstanceOfList
which return true if the input is instance ofList
We set up 4 tests :
inputIsInstanceOfList_listValue
: working test with a an array of 2 values, the input is an instance ofList
filterValueIsInstanceOfList_stringValue
: working test with aString
value (return false because it is not an array of values)filterValueIsInstanceOfList_withException
: test failing with the exception above when passing aList
of 2 valuesfilterValueIsInstanceOfList_withoutVariables
: test without exception but with an interrogation, we put the input value directly in the GraphQL query and we have anArrayValue
object, shall we have aList
instead ?After some research we don't see how to solve this issue (the exception) and finish our migration, could you help us ?
Thanks
The text was updated successfully, but these errors were encountered: