I am working on POC of jersey REST service to be consumed by js MVC framework. On one of the forms i need to return UserProfile object (serialized to JSON by Jackson) which will be used to pre-populate HTML form. On form submission only a subset of fields must be sent to server (since some fields like "role" are read-only and must not be changed) so input JSON will be mappped to UserProfileUpdateRequest object. From server-code maintenance point of view i would like to have have a relationship between these 2 objects, since UserProfileUpdateRequest will be a subset of UserProfile, so my first choice is to use composition: UserProfile contains UserProfileUpdateRequest.
The problem is that when UserProfile is serialized to JSON by jackson, all properties of referenced UserProfileRequest instance will be wrapped in userProfileRequest field- what seems to be quite natural but is not acceptable for JS guys (or at least i was told it is not acceptable). Is there any way i could force jackson to "flat" root object and point for which referenced objects its properties must be serialized under root? A little example
class UserProfileRequest{
private String a;
private String b;
...
}
class UserProfile{
private String role;
...
private UserProfileRequest userProfileRequest;
}
So when UserProfile is serialized i got:
{"role":"admin",...,"userProfileRequest":{"a":"...","b":"...",...}}
but would like to get
{"role":"admin",...,"a":"...","b":"...",...}
I am using Jackson 1.9.7.
I think you are looking for the #JsonUnwrapped annotation.
class UserProfile{
private String role;
...
#JsonUnwrapped
private UserProfileRequest userProfileRequest;
}
Edit: Here is the link to #JsonUnwrapped in Jackson 1.9.9, so it should be available in 1.9.7, too.
Related
I'm using Protostuff in an attempt to serialize/deserialize objects of several different types for which no protobuf sources are available (it's a server-server RPC scenario). Serialization goes OK because I know the type of the object to serialize and can create the schema:
Schema schema = RuntimeSchema.getSchema(object.getClass());
Now, I use ProtobufIOUtil.toByteArray and get a byte array which I then pass to a remote server. However, I can't seem to deserialize this byte array in the remote server because I have no way to create a schema for an object of "unknown" type. Is there any way I can get past this and use Protostuff in the same way I would use Java's native serialization?
There are few solutions with common idea - serialize name of the class together with the data.
First one requires protostuff-runtime. You should create wrapper class with one field of type Object:
public class Wrapper {
public Object data;
}
Then you put your object to data field and serialize wrapper, protostuff-runtime will append class name to serialized form automatically, and later use it for deserialization.
If you want more control, then you can do similar thing without protistuff-runtime.
First, you need a wrapper class:
public class Wrapper {
public String clazz;
public byte[] data;
}
Then you should serialize your data to byte array, store it to wrapper, and then serialize wrapper instance.
On remote side, you deserialize Wrapper first, then get clazz field - it is the class you should use to deserialize data.
I am reading JPA 2.0. I encounter a sentence that
We have used the transient modifier instead of the #Transient annotation so that
if the Employee gets serialized from one VM to another then the translated name
will get reinitialized to correspond to the locale of the new VM.
#Entity
public class Employee {
#Id private int id;
private String name;
private long salary;
transient private String translatedName;
// ...
public String toString() {
if (translatedName == null) {
translatedName = ResourceBundle.getBundle("EmpResources").getString("Employee");
}
return translatedName + ": " + id + " " + name;
}
}
What I understood is that when we use #Entity annotation and container encounter it then it call JPA provider that do the things. Like map id to ID column in database. Although we didn't mention the #Column annotation on the name and salary, but by default it maps to column NAME and SALARY in database. We used transient on translatedName so the JAP leave it as it is, not mapping applied to it. It's just a field in this class. But i am unable to get the understanding of the sentence
if the Employee gets serialized from one VM to another
Someone please explain it to me? Also tell me that what i defined above about the workflow of JAP is correct? Like what happening when container encounter #Entity annotation?
Thanks
When a class implements the java.io.Serializable interface, instances of this class are serializable. That means that the JVM can transform the object into a sequence of bytes. These bytes can be sent over the network, or saved on a disk, and can be read by another VM and transformed back into a Java object.
If a field has the transient Java keyword, it means that this field will be ignored by this serialization mechanism. The field won't be serialized.
A field annotated with #Transient is considered as a non-persistent field by JPA. It won't save it in the database, and it won't load it from the database. But it will be serialized if the object is sent to another JVM.
The Java transient keyword automatically makes a field #Transient. This means that a transient field, won't be serialized, and won't be saved by JPA either.
In the "JEE5 world" you can use detached entities as you would have used transfer objects. (I am not judging whether this is a good idea or not!)
Thus you can call for example a service method (e.g. EJB 3 SLSB method) that returns an instance of Employee remotely with the usual remote-call semantics regarding serialization.
It should be noted, that if an instance of Employee was serialized successfully, then your Java Runtime might be broken, as the class does not implement Serializable.
If you don't want to save the state of your entity arrtibute to DB and also don't want the state to get transferred to another jvm, then use Transient keyword.
If you don't want to save the state of your entity arrtibute to DB, but want the state to be transferred to another jvm, then use #Transient annotation.
In my Google Web Toolkit project, I got the following error:
com.google.gwt.user.client.rpc.SerializationException: Type ‘your.class.Type’ was not included in the set of types which can be serialized by this SerializationPolicy or its Class object could not be loaded. For security purposes, this type will not be serialized.
What are the possible causes of this error?
GWT keeps track of a set of types which can be serialized and sent to the client. your.class.Type apparently was not on this list. Lists like this are stored in .gwt.rpc files. These lists are generated, so editing these lists is probably useless. How these lists are generated is a bit unclear, but you can try the following things:
Make sure your.class.Type implements java.io.Serializable
Make sure your.class.Type has a public no-args constructor
Make sure the members of your.class.Type do the same
Check if your program does not contain collections of a non-serializable type, e.g. ArrayList<Object>. If such a collection contains your.class.Type and is serialized, this error will occur.
Make your.class.Type implement IsSerializable. This marker interface was specifically meant for classes that should be sent to the client. This didn't work for me, but my class also implemented Serializable, so maybe both interfaces don't work well together.
Another option is to create a dummy class with your.class.Type as a member, and add a method to your RPC interface that gets and returns the dummy. This forces the GWT compiler to add the dummy class and its members to the serialization whitelist.
I'll also add that if you want to use a nested class, use a static member class.
I.e.,
public class Pojo {
public static class Insider {
}
}
Nonstatic member classes get the SerializationException in GWT 2.4
I had the same issue in a RemoteService like this
public List<X> getX(...);
where X is an interface. The only implementation did conform to the rules, i.e. implements Serializable or IsSerializable, has a default constructor, and all its (non-transient and non-final) fields follow those rules as well.
But I kept getting that SerializationException until I changed the result type from List to X[], so
public X[] getX(...);
worked. Interestingly, the only argument being a List, Y being an interface, was no problem at all...
I have run into this problem, and if you per chance are using JPA or Hibernate, this can be a result of trying to return the query object and not creating a new object and copying your relavant fields into that new object. Check the following out, which I saw in a google group.
#SuppressWarnings("unchecked")
public static List<Article> getForUser(User user)
{
List<Article> articles = null;
PersistenceManager pm = PMF.get().getPersistenceManager();
try
{
Query query = pm.newQuery(Article.class);
query.setFilter("email == emailParam");
query.setOrdering("timeStamp desc");
query.declareParameters("String emailParam");
List<Article> results = (List<Article>) query.execute(user.getEmail
());
articles = new ArrayList<Article>();
for (Article a : results)
{
a.getEmail();
articles.add(a);
}
}
finally
{
pm.close();
}
return articles;
}
this helped me out a lot, hopefully it points others in the right direction.
Looks like this question is very similar to what IsSerializable or not in GWT?, see more links to related documentation there.
When your class has JDO annotations, then this fixed it for me (in addition to the points in bspoel's answer) : https://stackoverflow.com/a/4826778/1099376
I'd like to use for table storage an entity like this:
public class MyEntity
{
public String Text { get; private set; }
public Int32 SomeValue { get; private set; }
public MyEntity(String text, Int32 someValue)
{
Text = text;
SomeValue = someValue;
}
}
But it's not possible, because the ATS needs
Parameterless constructor
All properties public and
read/write.
Inherit from TableServiceEntity;
The first two, are two things I don't want to do. Why should I want that anybody could change some data that should be readonly? or create objects of this kind in a inconsistent way (what are .ctor's for then?), or even worst, alter the PartitionKey or the RowKey. Why are we still constrained by these deserialization requirements?
I don't like develop software in that way, how can I use table storage library in a way that I can serialize and deserialize myself the objects? I think that as long the objects inherits from TableServiceEntity it shouldn't be a problem.
So far I got to save an object, but I don't know how retrieve it:
Message m = new Message("message XXXXXXXXXXXXX");
CloudTableClient tableClient = account.CreateCloudTableClient();
tableClient.CreateTableIfNotExist("Messages");
TableServiceContext tcontext = new TableServiceContext(account.TableEndpoint.AbsoluteUri, account.Credentials);
var list = tableClient.ListTables().ToArray();
tcontext.AddObject("Messages", m);
tcontext.SaveChanges();
Is there any way to avoid those deserialization requirements or get the raw object?
Cheers.
If you want to use the Storage Client Library, then yes, there are restrictions on what you can and can't do with your objects that you want to store. Point 1 is correct. I'd expand point 2 to say "All properties that you want to store must be public and read/write" (for integer properties you can get away with having read only properties and it won't try to save them) but you don't actually have to inherit from TableServiceEntity.
TableServiceEntity is just a very light class that has the properties PartitionKey, RowKey, Timestamp and is decorated with the DataServiceKey attribute (take a look with Reflector). All of these things you can do to a class that you create yourself and doesn't inherit from TableServiceEntity (note that the casing of these properties is important).
If this still doesn't give you enough control over how you build your classes, you can always ignore the Storage Client Library and just use the REST API directly. This will give you the ability to searialize and deserialize the XML any which way you like. You will lose the all of the nice things that come with using the library, like ability to create queries in LINQ.
The constraints around that ADO.NET wrapper for the Table Storage are indeed somewhat painful. You can also adopt a Fat Entity approach as implemented in Lokad.Cloud. This will give you much more flexibility concerning the serialization of your entities.
Just don't use inheritance.
If you want to use your own POCO's, create your class as you want it and create a separate tableEntity wrapper/container class that holds the pK and rK and carries your class as a serialized byte array.
You can use composition to achieve what you want.
Create your Table Entities as you need to for storage and create your POCOs as wrappers on those providing the API you want the rest of your application code to see.
You can even mix in some interfaces for better code.
How about generating the POCO wrappers at runtime using System.Reflection.Emit http://blog.kloud.com.au/2012/09/30/a-better-dynamic-tableserviceentity/
I have document scanning system where several types of documents are scanned. Initially, the document has no information when its scanned, then they get classified and additional information is entered for them in a second step later. So, I have a base class called Document, and subclasses for each type with their respective metadata like below. I have it setup as a table-per-subclass (joined subclass) mapping in NHibernate.
public class Document
{
public int ID { get; set; }
public string FilePath { get; set; }
}
public class Certificate : Document
{
// certificate-specific fields
}
public class Correspondence : Document
{
// correspondence-specific fields
}
What I need to be able to do is create a Document class first and save it. Then retrieve in a second step later on and convert it to one of the subclass types and fill in the rest of its information. What would be the best approach to do this, and is this even possible with NHibernate? If at all possible I would like to retain the original document record, but its not a dealbreaker if I have to jettison it.
Unfortunately, NHibernate does not allow you to switch between subclasses after initial creation; to get this working the way you want, you have 3 options:
Use a native sql call to change the discriminator (and possibly) add or change any subclass-related fields.
Copy the contents of your object to a new object of the proper class and then delete the original.
Don't use subclasses, control the state of your object through an enumeration or some other mechanism that allows you to determine their type at run-time.
This issue has already been discussed here. I would go with Terry Wilcox's tip to use a role for this. Composition over inheritance.