I'm implementing a REST service using Camel's cxfrs component. Various examples I've seen around the inets say I can get the service to return a JSON serialization of the object in question using a cxf:providers tag, like so
<cxf:rsServer id="rsServer" address="${CXFserver}${service}" serviceClass="org.trinityhealth.esb.PersonService"
loggingFeatureEnabled="true" loggingSizeLimit="20">
<cxf:providers>
<bean id="jsonHandler" class="com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider" />
</cxf:providers>
</cxf:rsServer>
This compiles and deploys just fine. But no matter what variant of this config I try, the service responds with "No message body writer has been found for response class Person". The Person class has a "#XmlRootElement(name = "Person")" annotation in it, which I guess is great if I wanted XML produced. But I don't - I want JSON. Jackson has a ton of annotations, do I need to add one to the Person class to get my service to realize I want the class serialized by the Jackson writer?
I don't know Camel that well, but typically Jackson does NOT require root annotation, unlike JAXB (partly since JSON structure does not require name for root type), so it seems unlikely you would such annotation.
I am guessing that rather the registration does not succeed for some reason.
Related
When I naively use Jackson to convert to JSON i receive this exception:
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class org.apache.cayenne.access.DefaultDataRowStoreFactory and no properties discovered to create BeanSerializer
Edit: I'd like to do something like this:
ObjectContext context = cayenneRuntime.newContext();
List<User> users = ObjectSelect.query(User.class).select(context);
JsonObject json = Json.mapper.convertValue(obj, Map.class)
Are there any existing solutions? Thanks
Considering that in a general case Cayenne gives you not just objects, but a virtual graph of objects, serialization to JSON becomes a more quirky topic than it initially appears.
The short answer: you'd have manually build JSON for whatever subgraph of your object graph.
While not a direct answer, it may be worth mentioning that Agrest framework (ex. LinkRest) supports rule-based serialization of Cayenne object graphs to JSON. But it is not a standalone component. I.e. it will only work if you use it for your REST services.
I will give an example to better explain my question
my request:
POST
http://localhost:8080/users/
request body: (This gets posted)
{"name":"Matt",
"salary":10000,
"blog_url":"www.myblog.com",
"dept_name":"ENG"
}
class CustomRequest(object):
def __init__(self,name,salary,blog_url,dept_name):
self.name=name
self.salary=10000
self.blog_url=blog_url
self.dept_name=dept_name
models.py
class myUser(models.Model):
//fields -- username, salary
class myUserProfile(models.Model):
User=models.OneToOneField(user)
blog_url=models.URLfield()
dept_name=models.ForeignKey(Department)
#apiview(['POST'])
def createUser(customrequest):
myuser=user(customrequest.name, customrequest.salary)
myuser.save()
myuser.userprofile.blog_url(customrequest.blog_url)
myuser.userprofile.dept_name(customrequest.dept_name)
myuser.save()
I have been most of REST services using Java JAX-RS API. In this framework,
POST request body is automatically deserialized to the object that the method takes in( in the above example, it is customrequest). A developer can define an object with attributes that he is looking for in the POST request and then perform the business logic.
Now that we are thinking of migrating to Django, I am wondering if Django Rest Framework provides this kind of behavior out of box. If so, how would I do that?
Please note, in the JAX-RS world, there is no need for a developer to write a serializer. All that is needed is the transfer object where the incoming JSON gets deserailzed into.
I assume in Django, both a serializer and a transfer object is needed to achieve the same purpose.
In DRF, you have two options:
either you use ModelSerializer and you get the model instance automatically
or you use Serializer and you get the validated_data and do whatever you like with it
The serializer is the same as what you call transfer object, in the sense that both define the data structure and that both will hold the deserialized values.
For models, it is required for persistence, but that is also required in JAX-RS, unless you use the same classes as ORM entities(which is a bad design). So in JAX-RS you will have, for example, CustomRequest and JPA CustomRequestEntity
I am currently using the this Jackson plugin
Which serialized my cyclical graphs. Then on the client I use the JSOG to decode the {#ref} objects like this:
JSOG.decode(data)
The problem comes when I am trying to send the json back up to the server. If I don't do anything to the data I get a "Maximum call stack size exceeded", obviously because my js object is cyclical. I try using:
JSOG.stringify(data);
But then Jackson chokes on all the #id and #refs:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "#id"
Has any one figured out how to do this?
Both sides need to be able to support JSOG convention. It is not part of JSON specification, nor can it be automatically detected; so Jackson can not process it without help.
I'm trying to use AutoBean on the server and client to send and receive json data through AppEngines channel API. I don't want to store this data in the datastore. I already have a Proxy for this object that I use for the RequestFactoryServlet (which underneath just uses AutoBean anyways), so this should be doable. Instead of writing up a new Proxy for the object that exactly duplicates the Proxy for the RequestFactoryServlet, I'd like to just use the proxy that I use for the RequestFactoryServlet. The only problem is that I get an error while compiling that comes from my AutoBeanFactory.
Invoking generator
com.google.web.bindery.autobean.gwt.rebind.AutoBeanFactoryGenerator
[ERROR] The com.wmba.wmbaapp.shared.ObjectProxy parameterization is not simple, but the obj method does not provide a
delegate
So I'm not really sure what to do here. It seems like before I added the client side in, it's able to serialize the object into JSON just fine, but for some reason it doesn't like this. It sounds like it wants a delegate from me, but I can't find anything on this from the internet.
Anyone have any ideas?
Note: I also tried the same thing with EntityProxy (which is the base of the RequestFactory framework from what I read on the AutoBean page, but I get the same error).
The issue is that EntityProxy defines the stableId method which is not a getter (name doesn't start with get). That makes it a not simple bean, for which AutoBeans require a real bean instance to be wrapped in the created AutoBean (the delegate, passed as an argument of the type of the AutoBean –ObjectProxy in your case– to your obj method of the AutoBeanFactory).
In other words, AutoBeans expects your obj method to be of the form:
AutoBean<ObjectProxy> obj(ObjectProxy toWrap);
The simplest solution is to not try to reuse the entity proxy with AutoBeans.
You might be able to make it work though by annotating your AutoBeanFactory with:
#Category(EntityProxyCategory.class)
You might have to add #NoWrap(EntityProxyId.class) too, see http://code.google.com/p/google-web-toolkit/source/browse/trunk/user/src/com/google/web/bindery/requestfactory/vm/InProcessRequestFactory.java
It turned out for me that I had a property setter that had an empty parameter list in my Ojbect interface. It didn't have anything to do with the factory, except for the interface the factory was trying to create a proxy for:
interface Factory {
AutoBeans<MyObject> createObject();
}
interface MyObject {
String getProperty();
void setProperty();
}
A bone-headed mistake but held me up with this precise compiler error. Adding the Category annotation as mentioned in the previous answer identified the faulty property setter.
I want to convert my pojo to json with JAXB, my pojo have one to many relation, and when i convert my pojo to json, JAXB generate error "A cycle is detected in the object graph. This will cause infinitely deep XML".
I read from web that, this problem can be solved with help from #XmlID and #XmlIDREF, but there is one problem, my Id attribute is not String type but Long. and as far as i know #XmlID can be used only with String property.
Other web suggest using eclipselink MOXy, but MOXy cannot generate json.
As you mentioned in your question EclipseLink MOXy (I'm the tech lead) has the #XmlInverseReference annotation to solve the problem of bidirectional relationships. As of EclipseLink 2.4 MOXy can produce/consume JSON.
For More Information
http://bdoughan.blogspot.com/2010/07/jpa-entities-to-xml-bidirectional.html
http://blog.bdoughan.com/2011/08/json-binding-with-eclipselink-moxy.html
You have a cyclic reference problem in your definition.
Try putting #XmlTransient above the problematic definition.
Also, about XmlID and string type, see http://markmail.org/message/up6vrzjixxrvy5th.
The JAXB specification requires that the property marked with #XmlID be a String property.
MOXy impl allows to use long.
One hack to keep using full JAXB compliant implementation would be to duplicate your id in a String field (before serialising)
Don't know so much about JAXB but XStream makes you able to use different modes and some of these modes will give references to the xpath address (absolute or relative) of an element in your xml, if these elements are already displayed.
(And you can do Json with XStream)
I faced similar problem when I wanted to convert my POJO to JSON with JaxRS. The MoxyJsonProvider is the default option of eclipselink but it fails to parse the JSOG (where cycles exists in the JSON structure). Jackson Jaxb Provider does this better with ObjectMapper.
I have elaborated in this answer below, about how to invoke Jackson Provider instead of Moxy. You will need jackson packages in your pom xml.
https://stackoverflow.com/a/60319306/5076414