Is there a way to auto-bind a Spring GraphQL #Argument input to QueryDSL Predicate? - spring

In REST you can bind HTTP query params to the QueryDSL Predicate like this:
#QuerydslPredicate(root = MyClass.class) final Predicate predicate
What is the equivalent for GraphQL?
Say I have a custom input type
input MyFilter {
status: String
this: Float
that: String
# ..
}
and would like to seamlessly bind it to a GraphQL #Argument and subsequently pass it the QueryDSL predicate and then on to the #GraphQlRepository.

Related

Decompose incoming JSON to Objects by fields with Spring MVC

I need to decompose my incoming JSON by fields in me REST Controller with Spring Boot.
My request body:
{
"text": "my text",
"myEnum": "VALUE1"
}
And my controller:
#PatchMapping("/{id}")
Object updateEntity(#PathVariable Long id, String text, MyEnum myEnum) {
/* ... */
}
#RequestParam doesn't work because it's just for query string params, #RequestBody doesn't work too because it handle whole body. But I need decompose incoming body by fields and inject into controller. I know what I can use Map <String, String> for this, but I would like validate my incoming fields, and I have the fields with difference types. And I don't want to create one class by incoming body for each controller.
If I haven't misunderstood your requirement, the usual way to deal with incoming JSON is to define a class that reflects your expected input, and make that the controller method parameter annotated as RequestBody.
Spring Boot, by default, uses Jackson to deserialize to your class, and so if you use matching property names then you won't need any special annotations or setup. I think enums will be handled by default, as are other types (though you may need to provide some guidance for strings representing dates or timestamps). Any bad value will fail deserialisation, which I think you can handle in ControllerAdvice (though you'll want to double check that)

Deserialize nested Kotlin object in springMVC

I'm trying to deserialize a complex GET request into a structure of nested objects.
The GET requests looks like:
curl 'localhost:8080/?id=1&inner.id=1'
and the code should look like this:
class RootObj(val id: Int, inner: InnerObject)
class InnerObject(val id: Int)
#RestController
class SearchController {
#GetMapping(path = ["/"])
fun getRoot(rootObj: RootObj): String {
return "ok"
}
}
This doesn't work out of the box I guess because spring doesn't know how properly create this nested structure.
Parameter specified as non-null is null: [...] parameter inner","path":"/"}%
Is there a way to overcome this problem? Maybe providing a totally custom deserializer code?
As alternative solution, I guess I could flatten the object hierarchy but for doing so I must be able to map a query parameter like inner.id to a field named innerId
Spring can actually map the query params to the custom object directly, but you need to provide defaults to the params of the custom object constructor.
So you need to define your classes as below for it to work
class RootObj(val id: Int = 0, val inner: InnerObject = InnerObject(0))
class InnerObject(var id: Int = 0)
Do note that the id field of InnerObject would have to be declared as var for Spring to be able to map it. Then curl 'localhost:8080/?id=1&inner.id=1' would work fine.

Populate an object and pass it in a request parameter in GraphQL

How can we populate an object and pass it in a request parameter in GraphQL. For example, i want to get rid of sequence of parameters here in the GraphQL request and want to create an object and pass it as a single parameter.
{
allBooks(first:20, orderBy:"myRating"){
isn
title
authors
publisher
}
}
You can use GraphQL Input Types.
In your schema definition you need to define the input into something like:
input BooksInput {
first: Int
orderBy: String
}
And require it as the args type in your query, then use it as:
{
allBooks($input: {first:20, orderBy:"myRating"}){
isn
title
authors
publisher
}
}

Can a graphql query or mutation return a scalar value

Syntactically you can define a query or a mutation in the schema such that it returns a type.
However, an operation definition (i.e a query or mutation invoked by a client) has to have a SelectionSet, so I have to do:
mutation X { field }
So the result of my mutation or query has to be an object with fields, it can't be a scalar.
Is this right? It feels like I ought to be able to just return a scalar. The result is always wrapped in an envelope when sending across HTTP, so the result would be valid JSON either way (a simple scalar isn't strictly valid JSON).
Is my reading correct?
You can actually return a scalar, like Boolean or String
type Mutation {
hello(who: String!): String
}
The issuing this query
mutation foo {
hello("peter")
}
result would look like this
data.hello // string
Tested this with graphql-yoga + graphql-playground:

Group toghether Node properties and return as a view in Cypher

I am working with v2.2.3 of Neo4J and Spring Neo4j Data SDN 4
I want to return a few properties of a node using a cypher query and map them into attributes of a POJO.My function in Spring data repository looks something like this
#Query(
"MATCH(n:ServiceProvider{profileStatus:{pStatus},currentResidenceState:{location}}) RETURN n.name,n.currentResidenceAddress ,n.employmentStatus,"
+ "n.idProofType,n.idProofNumber
ORDER BY n.registrationDate DESC SKIP{skip} LIMIT {limit}")
List<AdminSearchMapResult> getServiceProviderRecords(
#Param("pStatus")String pStatus,
#Param("location")String location,
#Param("skip") int skip,#Param("limit")int limit);
I get an error like
Scalar response queries must only return one column. Make sure your cypher query only returns one item.
I think its because of the fact that I cant bundle all the returned attributes into a view that can map into the POJO
If I return the node itself and map it into a POJO it works
Kindly guide
This can be done using #QueryResult
Annotate the AdminSearchMapResult POJO with #QueryResult. For example:
#QueryResult
public class AdminSearchMapResult {
String name;
String currentResidenceAddress;
...
}
Optionally annotate properties with #Property(name = "n.idProofType") if the alias is different from the field name.

Resources