You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
If a lacinia resolver returns anything other than clojure.lang.IObj an exception is being generated. The reason for this is that it is somewhere in the call chain trying to attach meta-data to the returned value.
java.lang.ClassCastException: datomic.query.EntityMap cannot be cast to clojure.lang.IObj
This however is a bit awkward when working with plain Java return types like e.g. EntityMap from datomic.
We have worked around this by defining a custom resolver function (needed anyway to do namespaced keywords conversion).
(defnfind-object-type
[v]
(some->> v
(keys)
(filter #(="id" (name %)))
(first)
(namespace)))
(defndefault-field-resolver"This is a function that accepts a field name (a keyword) and returns a field resolver function for the field. This includes transforming to datomic namespaced keywords and wrapping/unwrapping DatomicEntity objects."
[field-name]
^ResolverResult (fn [ctx args v]
(let [value (if (instance? DatomicEntity v) ;; DatomicEntity is a record with only one field, the entity
(get (.entity v) (keyword (find-object-type (.entity v)) (name field-name)))
(get v field-name))]
(resolve-as
(if (instance? datomic.Entity value)
(wrappers/->DatomicEntity value)
value)))))
This is however only part of the solution as each root query needs to wrap it's datomic entity results in the clojure record.
We also would like our resolvers to return manifold deferred's instead of a lacinia promise because of code readability. This approach suffers the same issue as with a Datomic Entity and combining the two becomes more and more a problem.
Is there any infrastructure available to extend lacinia's default resolver functionality (not sure if I'm using the right terminology here). What would be sufficient for this use case:
a function that is applied before the returned resolver result is being passed down to the type tagging functionality. Here you could wrap everything.
the default resolver function that can unwrap results and get the values out for a given field (i.e. what you can specify now as ':default-field-resolver').
After giving it some thought, I could walk the schema to update the resolvers with the default-resolver-middleware function. But still, it would be easier if a datomic Entity (or any other Java object) would be a valid response object from a resolver.
We might need to look into changing the internal representation of a resolved value; today it is a map or seq of maps. We need a way to provide the value and its type tag when, as in your case, it doesn't support metadata. I would suggest a specialized record type with slots for the raw value and the type; we could then get away from using metadata for this purpose.
In terms of manifold and etc., we have informally discussed adding a schema compile option of a function to decorate resolver functions; this decorator could be responsible for converting a manifold deferred into a Lacinia ResolverResult ... ah, looking up, just like the middleware you describe.
See #58 for the part about middleware. I glanced over the Manifold docs, and it looks quite reasonable to add a wrapper to got from Manifold's Deferred to Lacinia's ResolverResult.
hlship
changed the title
requirement of lacinia resolvers to return a clojure.lang.IObj too strict?
Exception thrown if a field resolver returns anything but a IObj
May 9, 2017
If a lacinia resolver returns anything other than
clojure.lang.IObj
an exception is being generated. The reason for this is that it is somewhere in the call chain trying to attach meta-data to the returned value.java.lang.ClassCastException: datomic.query.EntityMap cannot be cast to clojure.lang.IObj
This however is a bit awkward when working with plain Java return types like e.g.
EntityMap
from datomic.We have worked around this by defining a custom resolver function (needed anyway to do namespaced keywords conversion).
This is however only part of the solution as each root query needs to wrap it's datomic entity results in the clojure record.
We also would like our resolvers to return manifold deferred's instead of a lacinia promise because of code readability. This approach suffers the same issue as with a Datomic Entity and combining the two becomes more and more a problem.
Is there any infrastructure available to extend lacinia's default resolver functionality (not sure if I'm using the right terminology here). What would be sufficient for this use case:
An example:
The text was updated successfully, but these errors were encountered: