-
Notifications
You must be signed in to change notification settings - Fork 131
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
net.greghaines.jesque.utils.NoSuchConstructorException #38
Comments
I work with @jml6m, we are doing something roughly like this to enqueue a job:
This seems to work ok. Our action is defined like this:
and:
When we try and deserialize our job into the action, we get the NoSuchConstructorException. It appears Jesque is attempting to call a constructor with an Object[] array of the fields in Foo, rather than with a deserialized Foo. I suppose this is rather obvious behavior since the API doesn't provide a way to tell Jesque which class to deserialize into. We are wondering if there is a supported use-case and if so, how do we do it? |
Behind the scenes, Jesque uses Jackson to serialize and de-serialize objects into and out of JSON. Jackson transparently handles most common objects (primitives & wrappers, Strings, collections), however, if you wish to send an object of your creation, you need to tell Jackson how to convert it back and forth from JSON. The easiest solution is to refactor to not use custom types but I know that is not always possible. Jesque leverages Jackson Data-Bind library which allows for registering custom serializers. Jesque has a singleton, ObjectMapperFactory that creates the shared Jackson ObjectMapper that is used throughout Jesque. You can see Jesque already registers custom serializers for Jesque types using a Feature Module on this ObjectMapper. Below is an example of how you would plug in your serializers: ObjectMapper mapper = ObjectMapperFactory.get()
mapper.registerModule(new SimpleModule("com.acme.jesque.project", Version.unknownVersion())
.addSerializer(Foo.class, new FooJsonSerializer())
.addDeserializer(Foo.class, new FooJsonDeserializer()); You can find examples of custom serializers in the net.greghaines.jesque.json package. |
@jml6m @jbcpollak Did this help? Do you have any other questions? |
A simpler workaround is to call:
Since the arguments are referred to by the Object superclass, Jackson will add the class name to the serialized JSON, this is used as a hint during deserialization to instantiate the correct class. Though, I still have a question about this. To me, it seems that there are two approaches to constructor matching:
Reading the source code of Jesque, it seems to follow approach (1). The advantage is that you only parse each JSON object once and it works well with supertypes. Approach (2) may be less efficient, since there may be multiple constructors with the correct number of arguments, and the first constructor may not be the correct one. Also, there may a problem when the constructor arguments are supertypes of the objects that were serialized. But in many cases the actual class will only have a small number of constructors (e.g. in our application they currently have one), with the actual types. The advantage of approach (2) is then that the deserialization is guided by the constructor arguments and does not require extra work on the part of the user to write custom serializers. Would it be a possibility to provide (2) als an alternative strategy to (1)? |
You are correct about that feature of Jackson. Just be aware that additional type information in the JSON is a Jackson-specific feature; if multiple languages/environments are involved, that feature may need to be handled in the other environments. (Jesque has striven to remain compatible with the original Resque and Coffee-Resque implementations so, that is why this is not enabled by default) Regarding your question, my preference is to take the simplest, most efficient approach here (Option 1), especially in light of the numerous options that Jackson provides. Any of the features of Jacskon (Jackson/JAXB annotations, polymorphic type info, custom serializers/de-serializers, etc.) may be used with Jesque to facilitate the conversion between types and JSON. Jackson is the industry standard in JSON marshaling for Java; I prefer to rely on their well-tested and documented capabilities rather than rolling my own solution. |
Can't find much information about this...it's being thrown in the ReflectionUtils.findConstructor() method...
My job has a proper constructor which takes one argument to fill its one attribute. I also added a blank, default constructor and that still didn't fix the problem. This Object's attribute is an object that also has properly defined constructors.
The text was updated successfully, but these errors were encountered: